diff options
author | tle | 2008-02-03 16:40:54 +0000 |
---|---|---|
committer | tle | 2008-02-03 16:40:54 +0000 |
commit | 7f7b20a5d66bf69e88734ead5036e4d6664aa381 (patch) | |
tree | 97dacecfda81e183389ab1c0adb3a83b953823ad /jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java | |
parent | 145c144380950bd4b49fd4597a1a0695cf7c8b7b (diff) | |
download | webtools.dali-7f7b20a5d66bf69e88734ead5036e4d6664aa381.tar.gz webtools.dali-7f7b20a5d66bf69e88734ead5036e4d6664aa381.tar.xz webtools.dali-7f7b20a5d66bf69e88734ead5036e4d6664aa381.zip |
Merged jpt_2_0_exp branch into Head.v20080202_Merged
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java')
-rw-r--r-- | jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java | 284 |
1 files changed, 228 insertions, 56 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java index 409dd1db3c..c2b7c55f88 100644 --- a/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java +++ b/jpa/plugins/org.eclipse.jpt.utility/src/org/eclipse/jpt/utility/internal/ClassTools.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 Oracle. All rights reserved. + * Copyright (c) 2005, 2008 Oracle. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0, which accompanies this distribution * and is available at http://www.eclipse.org/legal/epl-v10.html. @@ -42,11 +42,13 @@ public final class ClassTools { public static final char NESTED_CLASS_NAME_SEPARATOR = '$'; public static final char ARRAY_INDICATOR = '['; + public static final char TYPE_DECLARATION_ARRAY_OPEN = '['; + public static final char TYPE_DECLARATION_ARRAY_CLOSE = ']'; public static final char REFERENCE_CLASS_CODE = 'L'; public static final char REFERENCE_CLASS_NAME_DELIMITER = ';'; - private static PrimitiveClassCode[] PRIMITIVE_CLASS_CODES; // pseudo 'final' - lazy-initialized + private static Primitive[] PRIMITIVES; // pseudo-'final' - lazy-initialized public static final char BYTE_CODE = 'B'; public static final char CHAR_CODE = 'C'; public static final char DOUBLE_CODE = 'D'; @@ -56,8 +58,11 @@ public final class ClassTools { public static final char SHORT_CODE = 'S'; public static final char BOOLEAN_CODE = 'Z'; public static final char VOID_CODE = 'V'; - - private static int MAX_PRIMITIVE_CLASS_NAME_LENGTH = -1; // pseudo 'final' - lazy-initialized + private static int MAX_PRIMITIVE_CLASS_NAME_LENGTH = -1; // pseudo-'final' - lazy-initialized + private static int MAX_PRIMITIVE_WRAPPER_CLASS_NAME_LENGTH = -1; // pseudo-'final' - lazy-initialized + + public static final String VOID_CLASS_NAME = void.class.getName(); + public static final String VOID_WRAPPER_CLASS_NAME = java.lang.Void.class.getName(); /** @@ -391,14 +396,14 @@ public final class ClassTools { return field(object.getClass(), fieldName); } - /** + /* * Return a string representation of the specified constructor. */ private static String fullyQualifiedConstructorSignature(Class<?> javaClass, Class<?>[] parameterTypes) { return fullyQualifiedMethodSignature(javaClass, null, parameterTypes); } - /** + /* * Return a string representation of the specified field. */ private static String fullyQualifiedFieldName(Class<?> javaClass, String fieldName) { @@ -409,14 +414,14 @@ public final class ClassTools { return sb.toString(); } - /** + /* * Return a string representation of the specified field. */ private static String fullyQualifiedFieldName(Object object, String fieldName) { return fullyQualifiedFieldName(object.getClass(), fieldName); } - /** + /* * Return a string representation of the specified method. */ private static String fullyQualifiedMethodSignature(Class<?> javaClass, String methodName, Class<?>[] parameterTypes) { @@ -441,7 +446,7 @@ public final class ClassTools { return sb.toString(); } - /** + /* * Return a string representation of the specified method. */ private static String fullyQualifiedMethodSignature(Object receiver, String methodName, Class<?>[] parameterTypes) { @@ -454,7 +459,7 @@ public final class ClassTools { * Useful for accessing private, package, or protected fields. * Object#getFieldValue(String fieldName) */ - public static Object getFieldValue(Object object, String fieldName) { + public static Object fieldValue(Object object, String fieldName) { try { return attemptToGetFieldValue(object, fieldName); } catch (NoSuchFieldException nsfe) { @@ -468,7 +473,7 @@ public final class ClassTools { * Useful for accessing private, package, or protected fields. * Class#getStaticFieldValue(String fieldName) */ - public static Object getStaticFieldValue(Class<?> javaClass, String fieldName) { + public static Object staticFieldValue(Class<?> javaClass, String fieldName) { try { return attemptToGetStaticFieldValue(javaClass, fieldName); } catch (NoSuchFieldException nsfe) { @@ -830,7 +835,7 @@ public final class ClassTools { return newInstance(Class.forName(className, false, classLoader), parameterType, parameter); } - /** + /* * Push the declared fields for the specified class * onto the top of the stack. */ @@ -841,7 +846,7 @@ public final class ClassTools { } } - /** + /* * Push the declared methods for the specified class * onto the top of the stack. */ @@ -1263,21 +1268,25 @@ public final class ClassTools { /** * Return whether the specified class is a "reference" - * class (i.e. not void or one of the primitives). + * class (i.e. neither 'void' nor one of the primitive variable classes, + * ['boolean', 'int', 'float', etc.]). + * NB: void.class.isPrimitive() == true */ public static boolean classNamedIsReference(String className) { - return ! classNamedIsNonReference(className); + return ! classNamedIsPrimitive(className); } /** - * Return whether the specified class is a "non-reference" - * class (i.e. void or one of the primitives). + * Return whether the specified class is a primitive + * class (i.e. 'void' or one of the primitive variable classes, + * ['boolean', 'int', 'float', etc.]). + * NB: void.class.isPrimitive() == true */ - public static boolean classNamedIsNonReference(String className) { + public static boolean classNamedIsPrimitive(String className) { if (classNamedIsArray(className) || (className.length() > maxPrimitiveClassNameLength())) { return false; // performance tweak } - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { if (codes[i].javaClass.getName().equals(className)) { return true; @@ -1287,6 +1296,74 @@ public final class ClassTools { } /** + * Return whether the specified class is a "variable" primitive + * class (i.e. 'boolean', 'int', 'float', etc., but not 'void'). + * NB: void.class.isPrimitive() == true + */ + public static boolean classNamedIsVariablePrimitive(String className) { + return classNamedIsPrimitive(className) + && ( ! className.equals(VOID_CLASS_NAME)); + } + + /** + * Return whether the specified class is a primitive wrapper + * class (i.e. 'java.lang.Void' or one of the primitive variable wrapper classes, + * ['java.lang.Boolean', 'java.lang.Integer', 'java.lang.Float', etc.]). + * NB: void.class.isPrimitive() == true + */ + public static boolean classNamedIsPrimitiveWrapperClass(String className) { + if (classNamedIsArray(className) || (className.length() > maxPrimitiveWrapperClassNameLength())) { + return false; // performance tweak + } + Primitive[] codes = primitives(); + for (int i = codes.length; i-- > 0; ) { + if (codes[i].wrapperClass.getName().equals(className)) { + return true; + } + } + return false; + } + + /** + * Return whether the specified class is a "variable" primitive + * class (i.e. 'boolean', 'int', 'float', etc., but not 'void'). + * NB: void.class.isPrimitive() == true + */ + public static boolean classNamedIsVariablePrimitiveWrapperClass(String className) { + return classNamedIsPrimitiveWrapperClass(className) + && ( ! className.equals(VOID_WRAPPER_CLASS_NAME)); + } + + /** + * Return whether the specified class is a primitive wrapper + * class (i.e. 'java.lang.Void' or one of the primitive variable wrapper classes, + * ['java.lang.Boolean', 'java.lang.Integer', 'java.lang.Float', etc.]). + * NB: void.class.isPrimitive() == true + */ + public static boolean classIsPrimitiveWrapperClass(Class<?> javaClass) { + if (javaClass.isArray() || (javaClass.getName().length() > maxPrimitiveWrapperClassNameLength())) { + return false; // performance tweak + } + Primitive[] codes = primitives(); + for (int i = codes.length; i-- > 0; ) { + if (codes[i].wrapperClass == javaClass) { + return true; + } + } + return false; + } + + /** + * Return whether the specified class is a "variable" primitive + * class (i.e. 'boolean', 'int', 'float', etc., but not 'void'). + * NB: void.class.isPrimitive() == true + */ + public static boolean classIsVariablePrimitiveWrapperClass(Class<?> javaClass) { + return classIsPrimitiveWrapperClass(javaClass) + && (javaClass != java.lang.Void.class); + } + + /** * Return the class name for the specified class code. * @see java.lang.Class#getName() */ @@ -1307,7 +1384,7 @@ public final class ClassTools { * @see java.lang.Class#getName() */ public static Class<?> classForCode(char classCode) { - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { if (codes[i].code == classCode) { return codes[i].javaClass; @@ -1330,7 +1407,7 @@ public final class ClassTools { */ public static char codeForClass(Class<?> javaClass) { if (( ! javaClass.isArray()) && (javaClass.getName().length() <= maxPrimitiveClassNameLength())) { - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { if (codes[i].javaClass == javaClass) { return codes[i].code; @@ -1346,7 +1423,7 @@ public final class ClassTools { */ public static char codeForClassNamed(String className) { if (( ! classNamedIsArray(className)) && (className.length() <= maxPrimitiveClassNameLength())) { - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { if (codes[i].javaClass.getName().equals(className)) { return codes[i].code; @@ -1357,23 +1434,46 @@ public final class ClassTools { } /** - * Return the class for specified "type declaration". + * Return the class for the specified "type declaration". + */ + public static Class<?> classForTypeDeclaration(String typeDeclaration) throws ClassNotFoundException { + return classForTypeDeclaration(typeDeclaration, ClassTools.class.getClassLoader()); + } + + /** + * Return the class for the specified "type declaration", + * using the specified class loader. + */ + public static Class<?> classForTypeDeclaration(String typeDeclaration, ClassLoader classLoader) throws ClassNotFoundException { + TypeDeclaration td = typeDeclaration(typeDeclaration); + return classForTypeDeclaration(td.elementTypeName, td.arrayDepth); + } + + private static TypeDeclaration typeDeclaration(String typeDeclaration) { + typeDeclaration = StringTools.removeAllWhitespace(typeDeclaration); + int arrayDepth = arrayDepthForTypeDeclaration_(typeDeclaration); + String elementTypeName = typeDeclaration.substring(0, typeDeclaration.length() - (arrayDepth * 2)); + return new TypeDeclaration(elementTypeName, arrayDepth); + } + + /** + * Return the class for the specified "type declaration". */ public static Class<?> classForTypeDeclaration(String elementTypeName, int arrayDepth) throws ClassNotFoundException { return classForTypeDeclaration(elementTypeName, arrayDepth, null); } /** - * Return the class for specified "type declaration", + * Return the class for the specified "type declaration", * using the specified class loader. */ // see the "Evaluation" of jdk bug 6446627 for a discussion of loading classes public static Class<?> classForTypeDeclaration(String elementTypeName, int arrayDepth, ClassLoader classLoader) throws ClassNotFoundException { // primitives cannot be loaded via Class#forName(), // so check for a primitive class name first - PrimitiveClassCode pcc = null; + Primitive pcc = null; if (elementTypeName.length() <= maxPrimitiveClassNameLength()) { // performance tweak - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { if (codes[i].javaClass.getName().equals(elementTypeName)) { pcc = codes[i]; @@ -1403,7 +1503,44 @@ public final class ClassTools { } /** - * Return the class name for specified "type declaration". + * Return the class name for the specified "type declaration"; e.g. + * "int[]" -> "[I" + * @see java.lang.Class#getName() + */ + public static String classNameForTypeDeclaration(String typeDeclaration) { + TypeDeclaration td = typeDeclaration(typeDeclaration); + return classNameForTypeDeclaration(td.elementTypeName, td.arrayDepth); + } + + /** + * Return the array depth for the specified "type declaration"; e.g. + * "int[]" -> 1 + */ + public static int arrayDepthForTypeDeclaration(String typeDeclaration) { + return arrayDepthForTypeDeclaration_(StringTools.removeAllWhitespace(typeDeclaration)); + } + + /* + * Assume no whitespace in the type declaration. + */ + private static int arrayDepthForTypeDeclaration_(String typeDeclaration) { + int last = typeDeclaration.length() - 1; + int depth = 0; + int close = last; + while (typeDeclaration.charAt(close) == TYPE_DECLARATION_ARRAY_CLOSE) { + if (typeDeclaration.charAt(close - 1) == TYPE_DECLARATION_ARRAY_OPEN) { + depth++; + } else { + throw new IllegalArgumentException("invalid type declaration: " + typeDeclaration); + } + close = last - (depth * 2); + } + return depth; + } + + /** + * Return the class name for the specified "type declaration". + * @see java.lang.Class#getName() */ public static String classNameForTypeDeclaration(String elementTypeName, int arrayDepth) { // non-array @@ -1411,8 +1548,8 @@ public final class ClassTools { return elementTypeName; } - if (elementTypeName.equals(void.class.getName())) { - throw new IllegalArgumentException("'void' must have an array depth of zero: " + arrayDepth + '.'); + if (elementTypeName.equals(VOID_CLASS_NAME)) { + throw new IllegalArgumentException("'" + VOID_CLASS_NAME + "' must have an array depth of zero: " + arrayDepth + '.'); } // array StringBuilder sb = new StringBuilder(100); @@ -1421,9 +1558,9 @@ public final class ClassTools { } // look for a primitive first - PrimitiveClassCode pcc = null; + Primitive pcc = null; if (elementTypeName.length() <= maxPrimitiveClassNameLength()) { // performance tweak - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { if (codes[i].javaClass.getName().equals(elementTypeName)) { pcc = codes[i]; @@ -1452,7 +1589,7 @@ public final class ClassTools { private static int calculateMaxPrimitiveClassNameLength() { int max = -1; - PrimitiveClassCode[] codes = primitiveClassCodes(); + Primitive[] codes = primitives(); for (int i = codes.length; i-- > 0; ) { int len = codes[i].javaClass.getName().length(); if (len > max) { @@ -1462,24 +1599,46 @@ public final class ClassTools { return max; } - private static PrimitiveClassCode[] primitiveClassCodes() { - if (PRIMITIVE_CLASS_CODES == null) { - PRIMITIVE_CLASS_CODES = buildPrimitiveClassCodes(); - } - return PRIMITIVE_CLASS_CODES; - } - - private static PrimitiveClassCode[] buildPrimitiveClassCodes() { - PrimitiveClassCode[] result = new PrimitiveClassCode[9]; - result[0] = new PrimitiveClassCode(BYTE_CODE, byte.class); - result[1] = new PrimitiveClassCode(CHAR_CODE, char.class); - result[2] = new PrimitiveClassCode(DOUBLE_CODE, double.class); - result[3] = new PrimitiveClassCode(FLOAT_CODE, float.class); - result[4] = new PrimitiveClassCode(INT_CODE, int.class); - result[5] = new PrimitiveClassCode(LONG_CODE, long.class); - result[6] = new PrimitiveClassCode(SHORT_CODE, short.class); - result[7] = new PrimitiveClassCode(BOOLEAN_CODE, boolean.class); - result[8] = new PrimitiveClassCode(VOID_CODE, void.class); + private static int maxPrimitiveWrapperClassNameLength() { + if (MAX_PRIMITIVE_WRAPPER_CLASS_NAME_LENGTH == -1) { + MAX_PRIMITIVE_WRAPPER_CLASS_NAME_LENGTH = calculateMaxPrimitiveWrapperClassNameLength(); + } + return MAX_PRIMITIVE_WRAPPER_CLASS_NAME_LENGTH; + } + + private static int calculateMaxPrimitiveWrapperClassNameLength() { + int max = -1; + Primitive[] codes = primitives(); + for (int i = codes.length; i-- > 0; ) { + int len = codes[i].wrapperClass.getName().length(); + if (len > max) { + max = len; + } + } + return max; + } + + private static Primitive[] primitives() { + if (PRIMITIVES == null) { + PRIMITIVES = buildPrimitives(); + } + return PRIMITIVES; + } + + /** + * NB: void.class.isPrimitive() == true + */ + private static Primitive[] buildPrimitives() { + Primitive[] result = new Primitive[9]; + result[0] = new Primitive(BYTE_CODE, java.lang.Byte.class); + result[1] = new Primitive(CHAR_CODE, java.lang.Character.class); + result[2] = new Primitive(DOUBLE_CODE, java.lang.Double.class); + result[3] = new Primitive(FLOAT_CODE, java.lang.Float.class); + result[4] = new Primitive(INT_CODE, java.lang.Integer.class); + result[5] = new Primitive(LONG_CODE, java.lang.Long.class); + result[6] = new Primitive(SHORT_CODE, java.lang.Short.class); + result[7] = new Primitive(BOOLEAN_CODE, java.lang.Boolean.class); + result[8] = new Primitive(VOID_CODE, java.lang.Void.class); return result; } @@ -1492,14 +1651,27 @@ public final class ClassTools { } - // ********** member class ********** + // ********** member classes ********** - private static class PrimitiveClassCode { - char code; - Class<?> javaClass; - PrimitiveClassCode(char code, Class<?> javaClass) { + private static class Primitive { + final char code; + final Class<?> javaClass; + final Class<?> wrapperClass; + private static final String WRAPPER_CLASS_TYPE_FIELD_NAME = "TYPE"; + // e.g. java.lang.Boolean.TYPE => boolean.class + Primitive(char code, Class<?> wrapperClass) { this.code = code; - this.javaClass = javaClass; + this.wrapperClass = wrapperClass; + this.javaClass = (Class<?>) staticFieldValue(wrapperClass, WRAPPER_CLASS_TYPE_FIELD_NAME); + } + } + + private static class TypeDeclaration { + final String elementTypeName; + final int arrayDepth; + TypeDeclaration(String elementTypeName, int arrayDepth) { + this.elementTypeName = elementTypeName; + this.arrayDepth = arrayDepth; } } |