001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.util;
006:
007: import java.lang.reflect.Constructor;
008: import java.lang.reflect.Field;
009: import java.lang.reflect.Method;
010: import java.text.ParseException;
011:
012: /**
013: * Class utility methods
014: */
015: public class ClassUtils {
016:
017: private static final Class METHOD_CLASS = Method.class;
018: private static final Class CONSTRUCTOR_CLASS = Constructor.class;
019: private static final Class FIELD_CLASS = Field.class;
020:
021: /**
022: * Convert fully-qualified field name like "mypackage.MyClass.myField" into a specification which
023: * contains the fully-qualified class name and the field name.
024: * @param fieldName Fully-qualified field name
025: * @return Specification of class/field names
026: * @throws ParseException If the fieldName is not properly formatted
027: */
028: public static ClassSpec parseFullyQualifiedFieldName(
029: String fieldName) throws ParseException {
030: ClassSpecImpl rv = new ClassSpecImpl();
031: rv.parseFullyQualifiedFieldName(fieldName);
032: return rv;
033: }
034:
035: /**
036: * Get the dimension of an array
037: * @param arrayClass The array class
038: * @return Dimension, >= 0
039: * @throws NullPointerException If arrayClass is null
040: * @throws IllegalArgumentException If arrayClass is not an array class
041: */
042: public static int arrayDimensions(Class arrayClass) {
043: verifyIsArray(arrayClass); // guarantees c is non-null and an array class
044: return arrayClass.getName().lastIndexOf("[") + 1;
045: }
046:
047: /**
048: * If c is an array, return the reifiable type of the array element
049: * @param c Array class
050: * @return Type of an array element
051: * @throws NullPointerException If arrayClass is null
052: * @throws IllegalArgumentException If arrayClass is not an array class
053: */
054: public static Class baseComponentType(Class c) {
055: verifyIsArray(c); // guarantees c is non-null and an array class
056: while (c.isArray()) {
057: c = c.getComponentType();
058: }
059: return c;
060: }
061:
062: private static void verifyIsArray(Class arrayClass) {
063: if (arrayClass == null) {
064: throw new NullPointerException();
065: }
066: if (!arrayClass.isArray()) {
067: throw new IllegalArgumentException(arrayClass
068: + " is not an array type");
069: }
070: }
071:
072: /**
073: * Determine whether test is a primitive array
074: * @param test The object
075: * @return True if test is a non-null primitive array
076: */
077: public static boolean isPrimitiveArray(Object test) {
078: if (test == null) {
079: return false;
080: }
081: Class c = test.getClass();
082: if (!c.isArray()) {
083: return false;
084: }
085: return c.getComponentType().isPrimitive();
086: }
087:
088: /**
089: * Determine whether c is an enum (JDK 1.4 friendly)
090: * @param c Class
091: * @return True if enum
092: */
093: public static boolean isEnum(Class c) {
094: // a jdk1.4 friendly (but still fast) check for enums
095: Class super Class = c.getSuperclass();
096: if (super Class == null)
097: return false;
098: if (((c.getModifiers() & 0x00004000) != 0)
099: && isSubclassOfEnum(super Class)) {
100: return true;
101: }
102: return false;
103: }
104:
105: private static boolean isSubclassOfEnum(Class c) {
106: String name = c.getName();
107: while (!"java.lang.Enum".equals(name)) {
108: c = c.getSuperclass();
109: if (c == null) {
110: return false;
111: }
112: name = c.getName();
113: }
114: return true;
115: }
116:
117: /**
118: * Check whether c is a portable java reflection class like Method, Constructor, or Field
119: * @param c Class
120: * @return True if portable
121: */
122: public static boolean isPortableReflectionClass(Class c) {
123: return METHOD_CLASS == c || CONSTRUCTOR_CLASS == c
124: || FIELD_CLASS == c;
125: }
126:
127: /**
128: * Holder for a class name and field name which together fully identify a field
129: * @see ClassUtils#parseFullyQualifiedFieldName(String)
130: */
131: public interface ClassSpec {
132: /**
133: * @return Full class name
134: */
135: public String getFullyQualifiedClassName();
136:
137: /**
138: * @return Short field name
139: */
140: public String getShortFieldName();
141: }
142:
143: private static class ClassSpecImpl implements ClassSpec {
144:
145: private String fullyQualifiedClassName;
146: private String shortFieldName;
147:
148: private void parseFullyQualifiedFieldName(String fieldName)
149: throws ParseException {
150: if (fieldName == null)
151: throwNotFullyQualifiedFieldName(fieldName, 0);
152: int lastDot = fieldName.lastIndexOf('.');
153: if (lastDot <= 0)
154: throwNotFullyQualifiedFieldName(fieldName, 0);
155: if (lastDot + 1 == fieldName.length())
156: throwNotFullyQualifiedFieldName(fieldName, lastDot);
157: fullyQualifiedClassName = fieldName.substring(0, lastDot);
158: shortFieldName = fieldName.substring(lastDot + 1);
159: }
160:
161: private void throwNotFullyQualifiedFieldName(String fieldName,
162: int position) throws ParseException {
163: throw new ParseException(
164: "Not a fully qualified fieldname: " + fieldName,
165: position);
166: }
167:
168: public String getFullyQualifiedClassName() {
169: return this .fullyQualifiedClassName;
170: }
171:
172: public String getShortFieldName() {
173: return this .shortFieldName;
174: }
175:
176: public String toString() {
177: return "ClassSpec[classname=" + fullyQualifiedClassName
178: + ", shortFieldName=" + shortFieldName + "]";
179: }
180: }
181:
182: }
|