0001: /* Classes.java
0002:
0003: {{IS_NOTE
0004:
0005: Purpose: Utilities to handle Class
0006: Description:
0007: History:
0008: 2001/4/19, Tom M. Yeh: Created.
0009:
0010: }}IS_NOTE
0011:
0012: Copyright (C) 2001 Potix Corporation. All Rights Reserved.
0013:
0014: {{IS_RIGHT
0015: This program is distributed under GPL Version 2.0 in the hope that
0016: it will be useful, but WITHOUT ANY WARRANTY.
0017: }}IS_RIGHT
0018: */
0019: package org.zkoss.lang;
0020:
0021: import java.util.Map;
0022: import java.util.HashMap;
0023: import java.util.List;
0024: import java.util.LinkedList;
0025: import java.util.Collection;
0026: import java.util.Arrays;
0027: import java.util.Date;
0028: import java.lang.reflect.Constructor;
0029: import java.lang.reflect.AccessibleObject;
0030: import java.lang.reflect.Method;
0031: import java.lang.reflect.Field;
0032: import java.lang.reflect.InvocationTargetException;
0033: import java.lang.reflect.Modifier;
0034: import java.math.BigDecimal;
0035: import java.math.BigInteger;
0036:
0037: import org.zkoss.mesg.MCommon;
0038: import org.zkoss.mesg.Messages;
0039: import org.zkoss.lang.Strings;
0040: import org.zkoss.lang.Objects;
0041: import org.zkoss.math.BigDecimals;
0042: import org.zkoss.math.BigIntegers;
0043: import org.zkoss.util.MultiCache;
0044: import org.zkoss.util.Cache;
0045: import org.zkoss.util.IllegalSyntaxException;
0046: import org.zkoss.util.logging.Log;
0047:
0048: /**
0049: * Utilities to handle java.lang.Class
0050: *
0051: * @author tomyeh
0052: */
0053: public class Classes {
0054: private static final Log log = Log.lookup(Classes.class);
0055:
0056: /**
0057: * Instantiates a new instance of the specified class with
0058: * the specified arguments and argument types.
0059: *
0060: * <p>Note only public constructors are searched.
0061: *
0062: * @param cls the class of the instance to create
0063: * @param argTypes the argument types of the constructor to inovke
0064: * @param args the arguments to initialize the instance
0065: * @return the new instance
0066: *
0067: * @exception NoSuchMethodException if a matching method is not found
0068: * @exception InstantiationException if the class that declares the
0069: * underlying constructor represents an abstract class
0070: * @exception InvocationTargetException if the underlying constructor
0071: * throws an exception
0072: * @see #newInstance(String, Class[], Object[])
0073: */
0074: public static final Object newInstance(Class cls, Class[] argTypes,
0075: Object[] args) throws NoSuchMethodException,
0076: InstantiationException, InvocationTargetException,
0077: IllegalAccessException {
0078: return cls.getConstructor(argTypes).newInstance(args);
0079: }
0080:
0081: /**
0082: * Instantiates a new instance of the specified class with the
0083: * specified argument.
0084: *
0085: * <p>It searches all contructor for the first one that matches
0086: * the specified arguments.
0087: * @since 3.0.1
0088: */
0089: public static final Object newInstance(Class cls, Object[] args)
0090: throws NoSuchMethodException, InstantiationException,
0091: InvocationTargetException, IllegalAccessException {
0092: if (args == null || args.length == 0)
0093: return cls.newInstance();
0094:
0095: final Constructor[] cs = cls.getConstructors();
0096: for (int j = 0; j < cs.length; ++j) {
0097: final Class[] types = cs[j].getParameterTypes();
0098: if (types.length == args.length) {
0099: for (int k = args.length;;) {
0100: if (--k < 0)
0101: return cs[j].newInstance(args);
0102:
0103: final Object arg = args[k];
0104: final Class type = types[k];
0105: if (arg == null)
0106: if (type.isPrimitive())
0107: break; //mismatch
0108: else
0109: continue; //match
0110:
0111: if (type.isInstance(arg))
0112: continue; //match
0113: if (!type.isPrimitive()
0114: || !Primitives.toWrapper(type).isInstance(
0115: arg))
0116: break; //mismatch
0117: }
0118: }
0119: }
0120:
0121: final StringBuffer sb = new StringBuffer(80)
0122: .append("No contructor compatible with ");
0123: for (int j = 0; j < args.length; ++j)
0124: sb.append(j != 0 ? ", " : "[").append(
0125: args[j] != null ? args[j].getClass().getName()
0126: : null);
0127: throw new NoSuchMethodException(sb.append("] in ").append(
0128: cls.getName()).toString());
0129: }
0130:
0131: /**
0132: * Instantiates a new instance of the specified class name
0133: * with the specified arguments.
0134: *
0135: * <p>It uses Class.forName to get the class.
0136: *
0137: * @param clsName the class name of the instance to create
0138: * @param argTypes the argument types of the constructor to inovke
0139: * @param args the arguments to initialize the instance
0140: * @return the new instance
0141: *
0142: * @exception NoSuchMethodException if a matching method is not found
0143: * @exception InstantiationException if the class that declares the
0144: * underlying constructor represents an abstract class
0145: * @exception InvocationTargetException if the underlying constructor
0146: * throws an exception
0147: * @exception ClassNotFoundException if the specified class name is not a class
0148: * @see #newInstance(Class, Class[], Object[])
0149: */
0150: public static final Object newInstance(String clsName,
0151: Class[] argTypes, Object[] args)
0152: throws NoSuchMethodException, InstantiationException,
0153: InvocationTargetException, ClassNotFoundException,
0154: IllegalAccessException {
0155: return newInstance(Class.forName(clsName), argTypes, args);
0156: }
0157:
0158: /**
0159: * Creates and initializes a new instance of the specified class name
0160: * with the specified arguments, by use of {@link #forNameByThread}.
0161: *
0162: * <p>It uses {@link #forNameByThread} to get the class.
0163: *
0164: * @param clsName the class name of the instance to create
0165: * @param argTypes the argument types of the constructor to inovke
0166: * @param args the arguments to initialize the instance
0167: * @return the new instance
0168: *
0169: * @exception NoSuchMethodException if a matching method is not found
0170: * @exception InstantiationException if the class that declares the
0171: * underlying constructor represents an abstract class
0172: * @exception InvocationTargetException if the underlying constructor
0173: * throws an exception
0174: * @exception ClassNotFoundException if the specified class name is not a class
0175: * @see #newInstance(Class, Class[], Object[])
0176: */
0177: public static final Object newInstanceByThread(String clsName,
0178: Class[] argTypes, Object[] args)
0179: throws NoSuchMethodException, InstantiationException,
0180: InvocationTargetException, ClassNotFoundException,
0181: IllegalAccessException {
0182: return newInstance(forNameByThread(clsName), argTypes, args);
0183: }
0184:
0185: /**
0186: * Creates and initializes a new instance of the specified class name
0187: * with default constructor, by use of {@link #forNameByThread}.
0188: */
0189: public static final Object newInstanceByThread(String clsName)
0190: throws NoSuchMethodException, InstantiationException,
0191: InvocationTargetException, ClassNotFoundException,
0192: IllegalAccessException {
0193: return newInstance(forNameByThread(clsName), null, null);
0194: }
0195:
0196: /**
0197: * Returns the Class object of the specified class name, using
0198: * the current thread's context class loader.
0199: *
0200: * <p>In additions, it handles the primitive types, such as int and double.
0201: *
0202: * @param clsName fully qualified name of the desired class
0203: * @return the Class object representing the desired class
0204: * @exception ClassNotFoundException if the class cannot be located by the specified class loader
0205: */
0206: public static final Class forNameByThread(String clsName)
0207: throws ClassNotFoundException {
0208: clsName = toInternalForm(clsName);
0209: final Class cls = Primitives.toClass(clsName);
0210: return cls != null ? cls : Class.forName(clsName, true, Thread
0211: .currentThread().getContextClassLoader());
0212: }
0213:
0214: /**
0215: * Change class name to internal form (e.g. byte[] -> [B). If already in
0216: * internal form, then just return it.
0217: */
0218: public static final String toInternalForm(String clsName) {
0219: final int k = clsName.indexOf('[');
0220: if (k <= 0) { //not an array, or already in internal form
0221: return clsName; //just return
0222: }
0223:
0224: //component class
0225: final String elm = clsName.substring(0, k).trim();
0226: if (elm.length() == 0)
0227: throw new IllegalArgumentException(
0228: "Not a legal class name: \"" + clsName + '"');
0229:
0230: //array depth
0231: boolean leftb = false;
0232: final String stub = clsName.substring(k);
0233: final StringBuffer sb = new StringBuffer(128);
0234: for (int j = 0; j < stub.length(); j++) {
0235: final char ch = stub.charAt(j);
0236: if (ch == '[') {
0237: if (leftb)
0238: throw new IllegalArgumentException(
0239: "Not a legal class name: \"" + clsName
0240: + '"');
0241: leftb = true;
0242: sb.append('[');
0243: } else if (ch == ']') {
0244: if (!leftb)
0245: throw new IllegalArgumentException(
0246: "Not a legal class name: \"" + clsName
0247: + '"');
0248: leftb = false;
0249: }
0250: }
0251: if (leftb)
0252: throw new IllegalArgumentException(
0253: "Not a legal class name: \"" + clsName + '"');
0254:
0255: final char code = Primitives.getNotation(elm);
0256: if (code != (char) 0) {//primitive array
0257: sb.append(code);
0258: } else {//object array
0259: sb.append('L').append(elm).append(';');
0260: }
0261: return sb.toString();
0262: }
0263:
0264: /**
0265: * Gets the topmost interface of the specified class or interface that
0266: * implements or extends the specified interface.
0267: * For example, if A extends B, and C implements A,
0268: * then getTopInterface(C, B) returns A.
0269: *
0270: * <p>The interfaces implemented by the specified class is checked first,
0271: * and then the subclass.
0272: *
0273: * @param cls the class or interface
0274: * @param subIF the sub-interface
0275: * @return the topmost interface extending subIF, or null if subIF
0276: * is not implemented by cls
0277: */
0278: public static Class getTopmostInterface(Class cls, Class subIF) {
0279: if (cls.isInterface())
0280: return subIF.isAssignableFrom(cls) ? cls : null;
0281:
0282: while (cls != null) {
0283: final Class[] ifs = cls.getInterfaces();
0284: for (int j = 0; j < ifs.length; ++j)
0285: if (subIF.isAssignableFrom(ifs[j]))
0286: return ifs[j];
0287:
0288: cls = cls.getSuperclass();
0289: }
0290: return null;
0291: }
0292:
0293: /** Returns all interfaces that are implemented by the specified class.
0294: * <p>Unlike {@link Class#getInterfaces}, it recursively searches
0295: * for all derived classes.
0296: */
0297: public static Class[] getAllInterfaces(Class cls) {
0298: final List l = new LinkedList();
0299: while (cls != null) {
0300: final Class[] ifs = cls.getInterfaces();
0301: for (int j = 0; j < ifs.length; ++j)
0302: l.add(ifs[j]);
0303:
0304: cls = cls.getSuperclass();
0305: }
0306: final int sz = l.size();
0307: return (Class[]) l.toArray(new Class[sz]);
0308: }
0309:
0310: /**
0311: * Tests whether a class contains the specified method.
0312: * Only public methods are tested.
0313: *
0314: * @param cls the class to test
0315: * @param name the method name
0316: * @param paramTypes the list of parameter types
0317: * @return true if it contains the method
0318: */
0319: public static final boolean containsMethod(Class cls, String name,
0320: Class[] paramTypes) {
0321: try {
0322: cls.getMethod(name, paramTypes);
0323: return true;
0324: } catch (NoSuchMethodException ex) {//no found
0325: return false;
0326: }
0327: }
0328:
0329: /** Corrects a string to a valid Java name.
0330: * Currently, it only removes '-' and capitalizes the succeeding
0331: * character. Example, 'field-name' becomes 'fieldName'.
0332: */
0333: public final static String correctFieldName(String name) {
0334: int j = name.indexOf('-');
0335: if (j < 0)
0336: return name; //nothing to change
0337:
0338: for (final StringBuffer sb = new StringBuffer(name);;) {
0339: sb.deleteCharAt(j);
0340: if (sb.length() == j)
0341: return sb.toString();
0342:
0343: sb.setCharAt(j, Character.toUpperCase(sb.charAt(j)));
0344:
0345: j = sb.indexOf("-", j);
0346: if (j < 0)
0347: return sb.toString();
0348: }
0349: }
0350:
0351: /**
0352: * Convert an attribute name, returned by toAttributeName, to
0353: * a method name.
0354: *
0355: * <p>toMethodName("true", "is") => "isTrue"<br>
0356: * toMethodName("true", "") => "true"
0357: *
0358: * @param attrName the attribute name
0359: * @param prefix the prefix; one of is, get and set
0360: * @return the method name
0361: * @see #toAttributeName
0362: */
0363: public static final String toMethodName(String attrName,
0364: String prefix) {
0365: if (prefix.length() == 0)
0366: return attrName;
0367:
0368: StringBuffer sb = new StringBuffer(prefix);
0369: char[] buf = attrName.toCharArray();
0370: buf[0] = Character.toUpperCase(buf[0]);
0371: return sb.append(buf).toString();
0372: }
0373:
0374: /**
0375: * Tests if a method name is an attribute, i.e., prefixing with is,
0376: * get or set. Caller could then test if it is a setter or getter
0377: * by charAt(0)=='s'.
0378: *
0379: * <p>Note 'set' is considered as an attribute, whose name is an
0380: * empty string.
0381: *
0382: * @param methodName the method name to test
0383: * @return true if it is setter or getter
0384: */
0385: public static final boolean isAttribute(String methodName) {
0386: int len = methodName.length();
0387: if (len < 2)
0388: return false;
0389:
0390: int j;
0391: switch (methodName.charAt(0)) {
0392: case 's':
0393: case 'g':
0394: if (len < 3 || methodName.charAt(1) != 'e'
0395: || methodName.charAt(2) != 't')
0396: return false;
0397: j = 3;
0398: break;
0399: case 'i':
0400: if (methodName.charAt(1) != 's')
0401: return false;
0402: j = 2;
0403: break;
0404: default:
0405: return false;
0406: }
0407: return j == len || Character.isUpperCase(methodName.charAt(j));
0408: }
0409:
0410: /**
0411: * Converts a method name to an attribute name by removing the prefix
0412: * is, get or set, or null if it doesn't start with is, get or set.
0413: *
0414: * <p>The code is optimized for better performance.
0415: *
0416: * @param methodName the method name
0417: * @return the attribute name; null if it is not an attribute name
0418: * @see #toMethodName
0419: */
0420: public static final String toAttributeName(String methodName) {
0421: int len = methodName.length();
0422: if (len < 2)
0423: return null;
0424:
0425: int j;
0426: switch (methodName.charAt(0)) {
0427: case 's':
0428: case 'g':
0429: if (len < 3 || methodName.charAt(1) != 'e'
0430: || methodName.charAt(2) != 't')
0431: return null;
0432: j = 3;
0433: break;
0434: case 'i':
0435: if (methodName.charAt(1) != 's')
0436: return null;
0437: j = 2;
0438: break;
0439: default:
0440: return null;
0441: }
0442: if (j == len || Character.isUpperCase(methodName.charAt(j))) {
0443: char[] buf = new char[len - j];
0444: if (buf.length > 0) {
0445: methodName.getChars(j, len, buf, 0);
0446: buf[0] = Character.toLowerCase(buf[0]);
0447: }
0448: return new String(buf);
0449: }
0450: return null;
0451: }
0452:
0453: //--Support Class--
0454: /**The method info class used for {@link #parseMethod(String signature)}.
0455: * This info describe the method return type, method name and two collections for
0456: * arguments type and arguments name;
0457: */
0458: public static class MethodInfo {
0459: /** The return type (class name), or null if no specified. */
0460: public String returnType;
0461: public String method;
0462: public String[] argTypes;
0463: public String[] argNames;
0464: public String throwsEx;
0465:
0466: //constructor
0467: protected MethodInfo(String r, String m, String[] argTs,
0468: String[] argNs, String tEx) {
0469: returnType = r;
0470: method = m;
0471: argTypes = argTs;
0472: argNames = argNs;
0473: throwsEx = tEx;
0474: }
0475: }
0476:
0477: /**
0478: * Gets the method information from a signature.
0479: * It returns a method info with the return type, method name and two collections
0480: * of arguments type and arguments name.
0481: *
0482: * @param signature the method signature.
0483: * @return MethodInfo The method information including return type, method name
0484: * and two collections for argument type annd arguments name.
0485: */
0486: public static final MethodInfo parseMethod(String signature)
0487: throws IllegalSyntaxException {
0488: int len = signature.length();
0489: int j = Strings.skipWhitespaces(signature, 0);
0490: int k = Strings.anyOf(signature, "( \t\n\r", j);
0491: k = Strings.skipWhitespaces(signature, k);
0492: if (k >= len)
0493: throw new IllegalSyntaxException(signature);
0494:
0495: String returnType = null;
0496: char cc = signature.charAt(k);
0497: if (cc != '(') {
0498: //skip the return type
0499: returnType = signature.substring(j, k).trim();
0500: //
0501: j = k;
0502: k = signature.indexOf('(', j + 1);
0503: if (k < 0)
0504: throw new IllegalSyntaxException(signature);
0505: }
0506: String method = signature.substring(j, k).trim();
0507:
0508: Collection argTypes = new LinkedList();
0509: Collection argNames = new LinkedList();
0510: do {
0511: j = Strings.skipWhitespaces(signature, k + 1);
0512: if (signature.charAt(j) == ')')
0513: break;
0514: k = Strings.anyOf(signature, ",) \t\n\r", j);
0515: k = Strings.skipWhitespaces(signature, k);
0516: if (k >= len)
0517: throw new IllegalSyntaxException(signature);
0518: argTypes.add(signature.substring(j, k).trim());
0519:
0520: cc = signature.charAt(k);
0521: if (cc != ',' && cc != ')') { //parameter name found
0522: k = Strings.anyOf(signature, ",) \t\n\r", j = k);
0523: k = Strings.skipWhitespaces(signature, k);
0524: argNames.add(signature.substring(j, k).trim());
0525:
0526: k = Strings.anyOf(signature, ",)", k);
0527: if (k >= len)
0528: throw new IllegalSyntaxException(signature);
0529: } else {
0530: argNames.add(""); //no name specified
0531: }
0532: } while (signature.charAt(k) == ',');
0533:
0534: assert argTypes.size() == argNames.size();
0535:
0536: //process throws ...
0537: String strThrows = "throws";
0538: String tEx = null;
0539: j = signature.indexOf(strThrows, k);
0540: if (j >= k && j < len) { //got throws
0541: k = signature.indexOf(';', j);
0542: if (k >= 0)
0543: tEx = signature.substring(j + strThrows.length(), k)
0544: .trim();
0545: else
0546: tEx = signature.substring(j + strThrows.length(), len)
0547: .trim();
0548: }
0549:
0550: return new MethodInfo(returnType, method, (String[]) argTypes
0551: .toArray(new String[argTypes.size()]),
0552: (String[]) argNames
0553: .toArray(new String[argNames.size()]), tEx);
0554: }
0555:
0556: /**
0557: * Gets the method based on the signature. It also returns the parameter
0558: * names to the params list.
0559: *
0560: * <p>Like {@link #getMethodInPublic(Class, String, Class[])}, it returns
0561: * only public method in a public class/interface.
0562: *
0563: * <p>For example, "find(java.lang.String name)" will return
0564: * the method with one String-typed argument and params will hold "name".
0565: * The return type is optional (actualy ignored).
0566: *
0567: * <p>If params is null, the parameter names are not returned and
0568: * the signature could be simplified as "find(java.lang.String)".
0569: *
0570: * <p>A cache mechanism is implemented, so you don't need to cache it
0571: * again in the caller.
0572: *
0573: * @param cls the class to look
0574: * @param signature the method signature; the return type is optional
0575: * @param params the collection to hold the parameter names returned;
0576: * null means no parameter names to return
0577: */
0578: public static final Method getMethodBySignature(Class cls,
0579: String signature, Collection params)
0580: throws NoSuchMethodException, ClassNotFoundException {
0581: MethodInfo mi = parseMethod(signature);
0582:
0583: LinkedList argTypes = new LinkedList();
0584: for (int i = 0; i < mi.argTypes.length; i++) {
0585: argTypes.add(forNameByThread(mi.argTypes[i]));
0586: if (params != null)
0587: params.add(mi.argNames[i]); //param name found
0588: }
0589:
0590: return getMethodInPublic(cls, mi.method, (Class[]) argTypes
0591: .toArray(new Class[argTypes.size()]));
0592: }
0593:
0594: /**
0595: * Gets the method that is declared in a public class/interface.
0596: *
0597: * <p>Class.getMethod returns a public method but the class itself
0598: * might not be public. However, in many cases, that class
0599: * also implements a public interface or class.
0600: *
0601: * <p>This method will search all its public classes to look for
0602: * the method that is 'real' public.
0603: *
0604: * <p>NoSuchMethodException is thrown if no public
0605: * class/interface is found to have the method.
0606: */
0607: public static final Method getMethodInPublic(Class cls,
0608: String name, Class[] argTypes) throws NoSuchMethodException {
0609: final Method m = cls.getMethod(name, argTypes);
0610: if (Modifier.isPublic(m.getDeclaringClass().getModifiers()))
0611: return m;
0612:
0613: final Class[] clses = cls.getInterfaces();
0614: for (int j = 0; j < clses.length; ++j)
0615: try {
0616: return getMethodInPublic(clses[j], name, argTypes);
0617: } catch (NoSuchMethodException ex) { //ignore it
0618: }
0619:
0620: final Class basecls = cls.getSuperclass();
0621: if (basecls != null)
0622: try {
0623: return getMethodInPublic(basecls, name, argTypes);
0624: } catch (NoSuchMethodException ex) { //ignore it
0625: }
0626:
0627: throw new NoSuchMethodException(cls + ": " + name + " "
0628: + Objects.toString(argTypes));
0629: }
0630:
0631: /** Gets one of the close method by specifying the arguments, rather
0632: * than the argument types. It actually calls {@link #getCloseMethod}.
0633: */
0634: public static final Method getMethodByObject(Class cls,
0635: String name, Object[] args) throws NoSuchMethodException {
0636: if (args == null)
0637: return getMethodInPublic(cls, name, null);
0638:
0639: final Class[] argTypes = new Class[args.length];
0640: for (int j = 0; j < args.length; ++j)
0641: argTypes[j] = args[j] != null ? args[j].getClass() : null;
0642: return getCloseMethod(cls, name, argTypes);
0643: }
0644:
0645: /**
0646: * Gets one of the close methods -- a close method is a method
0647: * with the same name and the compatible argument type.
0648: * By compatiable we mean the real method's argument type is
0649: * the same as or a superclass of the specified one.
0650: *
0651: * <p>It might not be the best fit one, unless there is a method
0652: * whose argument types are exactly argTypes.
0653: *
0654: * <p>You might specify the exact number in argTypes. If any of them is
0655: * unknwon, use null. Example, in the following, the first argument could
0656: * be anything and the second is anything deriving from MyClass:<br>
0657: * <code>new Class[] {null, MyClass.class}</code>
0658: *
0659: * <p>Note: if an argument accepts int, then Integer is considered
0660: * as compatible (unlike Class.getMethod). So are long, byte...
0661: *
0662: * <p>A cache mechanism is implemented, so you don't need to cache it
0663: * again in the caller.
0664: *
0665: * @param cls the class to locate the method
0666: * @param name the method name
0667: * @param argTypes an array of the argument classes;
0668: * null to denote no argument at all (i.e., exact match).
0669: * Any argTypes[i] could be null to denote any class.
0670: * @return the method
0671: * @exception NoSuchMethodException if the method is not found
0672: */
0673: public static final Method getCloseMethod(Class cls, String name,
0674: Class[] argTypes) throws NoSuchMethodException {
0675: if (argTypes == null || argTypes.length == 0)
0676: return getMethodInPublic(cls, name, null);
0677:
0678: final AOInfo aoi = new AOInfo(cls, name, argTypes, 0);
0679: Method m = (Method) _closms.get(aoi);
0680: if (m != null)
0681: return m;
0682:
0683: m = myGetCloseMethod(cls, name, argTypes, false);
0684: _closms.put(aoi, m);
0685: return m;
0686: }
0687:
0688: /**
0689: * Like {@link #getCloseMethod} to get a 'close' method, but
0690: * it look for subclass of the arguement (instead of superclass).
0691: * In other words, it looks for the method whose argument type is
0692: * the same as or a subclass of the specified one.
0693: */
0694: public static final Method getCloseMethodBySubclass(Class cls,
0695: String name, Class[] argTypes) throws NoSuchMethodException {
0696: if (argTypes == null || argTypes.length == 0)
0697: return getMethodInPublic(cls, name, null);
0698:
0699: final AOInfo aoi = new AOInfo(cls, name, argTypes,
0700: B_BY_SUBCLASS);
0701: Method m = (Method) _closms.get(aoi);
0702: if (m != null)
0703: return m;
0704:
0705: m = myGetCloseMethod(cls, name, argTypes, true);
0706: _closms.put(aoi, m);
0707: return m;
0708: }
0709:
0710: private static Cache _closms = new MultiCache(20, 1024,
0711: 4 * 60 * 60 * 1000);
0712:
0713: private static final Method myGetCloseMethod(final Class cls,
0714: final String name, final Class[] argTypes,
0715: final boolean bySubclass) throws NoSuchMethodException {
0716: assert D.OFF || argTypes != null : "Caller shall handle null";
0717: for (int j = 0;; ++j) {
0718: if (j == argTypes.length) {//all argTypes[j] non-null
0719: try {
0720: return getMethodInPublic(cls, name, argTypes);
0721: } catch (NoSuchMethodException ex) { //ignore it
0722: break;
0723: }
0724: }
0725: if (argTypes[j] == null) //specil handling required
0726: break;
0727: }
0728:
0729: final Method[] ms = cls.getMethods();
0730: for (int j = 0; j < ms.length; ++j) {
0731: if (!ms[j].getName().equals(name))
0732: continue;
0733:
0734: final Class[] mTypes = ms[j].getParameterTypes();
0735: if (mTypes.length != argTypes.length)
0736: continue; //not matched
0737:
0738: final boolean bPublic = Modifier.isPublic(ms[j]
0739: .getDeclaringClass().getModifiers());
0740: for (int k = 0;; ++k) {
0741: if (k == argTypes.length) { //all matched
0742: if (bPublic)
0743: return ms[j];
0744: try {
0745: return getMethodInPublic(cls, ms[j].getName(),
0746: ms[j].getParameterTypes());
0747: } catch (NoSuchMethodException ex) {
0748: }
0749: break;//not match; look for next
0750: }
0751:
0752: final Class argType = argTypes[k], mType = mTypes[k];
0753: if (argType == null
0754: || (!bySubclass && mType
0755: .isAssignableFrom(argType))
0756: || (bySubclass && argType
0757: .isAssignableFrom(mType)))
0758: continue; //match
0759:
0760: final Class c = Primitives.toPrimitive(argType);
0761: if (c == null || !c.equals(mType))
0762: break; //not match
0763: }
0764: }
0765: throw new NoSuchMethodException(cls + ": " + name
0766: + " argTypes: " + Objects.toString(argTypes));
0767: }
0768:
0769: /** Returns all close methods that match the specified condition, or
0770: * a zero-length array if none is found.
0771: * <p>Unlike {@link #getCloseMethod}, we don't cache the searched result,
0772: * and it won't throw any exception.
0773: */
0774: public static final Method[] getCloseMethods(Class cls,
0775: String name, Class[] argTypes) {
0776: if (argTypes == null || argTypes.length == 0) {
0777: try {
0778: return new Method[] { getMethodInPublic(cls, name, null) };
0779: } catch (NoSuchMethodException ex) {
0780: return new Method[0];
0781: }
0782: }
0783: return myGetCloseMethods(cls, name, argTypes, false);
0784: }
0785:
0786: /**
0787: * Like {@link #getCloseMethods} to get all 'close' methods, but
0788: * it look for subclass of the arguement (instead of superclass).
0789: * In other words, it looks for the method whose argument type is
0790: * the same as or a subclass of the specified one.
0791: */
0792: public static final Method[] getCloseMethodsBySubclass(Class cls,
0793: String name, Class[] argTypes) {
0794: if (argTypes == null || argTypes.length == 0)
0795: return getCloseMethods(cls, name, null);
0796: return myGetCloseMethods(cls, name, argTypes, true);
0797: }
0798:
0799: private static final Method[] myGetCloseMethods(final Class cls,
0800: final String name, final Class[] argTypes,
0801: final boolean bySubclass) {
0802: assert D.OFF || argTypes != null : "Caller shall handle null";
0803: final List mtds = new LinkedList();
0804: final Method[] ms = cls.getMethods();
0805: for (int j = 0; j < ms.length; ++j) {
0806: if (!ms[j].getName().equals(name))
0807: continue;
0808:
0809: final Class[] mTypes = ms[j].getParameterTypes();
0810: if (mTypes.length != argTypes.length)
0811: continue; //not matched
0812:
0813: final boolean bPublic = Modifier.isPublic(ms[j]
0814: .getDeclaringClass().getModifiers());
0815: for (int k = 0;; ++k) {
0816: if (k == argTypes.length) { //all matched
0817: if (bPublic) {
0818: mtds.add(ms[j]);
0819: } else {
0820: try {
0821: mtds.add(getMethodInPublic(cls, ms[j]
0822: .getName(), ms[j]
0823: .getParameterTypes()));
0824: } catch (NoSuchMethodException ex) { //ignore; not add
0825: }
0826: }
0827: break; //found; next method
0828: }
0829:
0830: final Class argType = argTypes[k], mType = mTypes[k];
0831: if (argType == null
0832: || (!bySubclass && mType
0833: .isAssignableFrom(argType))
0834: || (bySubclass && argType
0835: .isAssignableFrom(mType)))
0836: continue; //match one argument
0837:
0838: final Class c = Primitives.toPrimitive(argType);
0839: if (c == null || !c.equals(mType))
0840: break; //not match; next method
0841: }
0842: }
0843: return (Method[]) mtds.toArray(new Method[mtds.size()]);
0844: }
0845:
0846: /**
0847: * Search the get method; not imply B_METHODONLY.
0848: */
0849: public static final int B_GET = 0; //must be 0
0850: /**
0851: * Search the set method; not imply B_METHODONLY.
0852: */
0853: public static final int B_SET = 1; //must be 1
0854: /**
0855: * Only search for public methods or fields.
0856: */
0857: public static final int B_PUBLIC_ONLY = 0x0002;
0858: /**
0859: * Only search for methods; excluding fields.
0860: */
0861: public static final int B_METHOD_ONLY = 0x0004;
0862:
0863: /** Used by {@link #getCloseMethodBySubclass} to distiquish
0864: * {@link #getCloseMethod}.
0865: */
0866: private static final int B_BY_SUBCLASS = 0x1000;
0867:
0868: /**
0869: * Gets the specified accessible object, either a method or a field, by
0870: * searching the specified name.
0871: *
0872: * <p>The search sequence is: (assume field name is body)><br>
0873: * getBody(...)<br>
0874: * isBody(...)<br>
0875: * body(...)<br>
0876: * body
0877: *
0878: * <p>If B_SET is specified, setBody(...) is searched instead of
0879: * getBody(...) and isBody(...). The field is searched only if
0880: * argsType.length is 0 or 1.
0881: *
0882: * <p>Note: it uses {@link #getCloseMethod} to get the method.
0883: *
0884: * <p>A cache mechanism is implemented, so you don't need to cache it
0885: * again in the caller.
0886: *
0887: * @param cls the class to find
0888: * @param name the name of the accessible object
0889: * @param argTypes the parameter type of the method to find
0890: * @param flags a combination of B_xxx or zero
0891: * @return the accessible object; either Field or Method
0892: * @exception NoSuchMethodException if neither the set method of
0893: * specified field nor the field itself not found
0894: * @exception SecurityException if access to the information is denied
0895: */
0896: public static final AccessibleObject getAccessibleObject(Class cls,
0897: String name, Class[] argTypes, int flags)
0898: throws NoSuchMethodException {
0899: final AOInfo aoi = new AOInfo(cls, name, argTypes, flags);
0900: AccessibleObject ao = (AccessibleObject) _acsos.get(aoi);
0901: if (ao != null)
0902: return ao;
0903:
0904: ao = myGetAcsObj(cls, name, argTypes, flags);
0905: _acsos.put(aoi, ao);
0906: return ao;
0907: }
0908:
0909: private static Cache _acsos = new MultiCache(20, 600,
0910: 4 * 60 * 60 * 1000);
0911:
0912: private static final AccessibleObject myGetAcsObj(Class cls,
0913: String name, Class[] argTypes, int flags)
0914: throws NoSuchMethodException {
0915: //try public set/get
0916: final String decoratedName = toMethodName(name,
0917: (flags & B_SET) != 0 ? "set" : "get");
0918: try {
0919: return getCloseMethod(cls, decoratedName, argTypes);
0920: } catch (NoSuchMethodException ex) { //ignore
0921: }
0922:
0923: //try public is
0924: String isMethodName = null;
0925: if ((flags & B_SET) == 0)
0926: try {
0927: isMethodName = toMethodName(name, "is");
0928: return getCloseMethod(cls, isMethodName, argTypes);
0929: } catch (NoSuchMethodException ex) { //ignore
0930: }
0931:
0932: //try public same
0933: try {
0934: return getCloseMethod(cls, name, argTypes);
0935: } catch (NoSuchMethodException ex) {
0936: if ((flags & (B_PUBLIC_ONLY | B_METHOD_ONLY)) == (B_PUBLIC_ONLY | B_METHOD_ONLY))
0937: throw ex;
0938: }
0939:
0940: if ((flags & B_PUBLIC_ONLY) == 0) {
0941: //try any set/get
0942: try {
0943: return getAnyMethod(cls, decoratedName, argTypes);
0944: } catch (NoSuchMethodException ex) { //ignore
0945: }
0946:
0947: //try any is
0948: if ((flags & B_SET) == 0)
0949: try {
0950: return getAnyMethod(cls, isMethodName, argTypes);
0951: } catch (NoSuchMethodException ex) { //ignore
0952: }
0953:
0954: //try any same
0955: try {
0956: return getAnyMethod(cls, name, argTypes);
0957: } catch (NoSuchMethodException ex) {
0958: if ((flags & B_METHOD_ONLY) != 0)
0959: throw ex;
0960: }
0961: }
0962:
0963: if (argTypes != null && argTypes.length > 1)
0964: throw new NoSuchMethodException(cls + ": " + name + " "
0965: + Objects.toString(argTypes));
0966:
0967: try {
0968: //try public field
0969: try {
0970: return cls.getField(name);
0971: } catch (NoSuchFieldException ex) { //ignore
0972: if ((flags & B_PUBLIC_ONLY) != 0)
0973: throw ex;
0974: }
0975:
0976: //try any field
0977: return getAnyField(cls, name);
0978: } catch (NoSuchFieldException ex) { //ignore
0979: throw new NoSuchMethodException(cls + ": name=" + name
0980: + " args=" + Objects.toString(argTypes));
0981: }
0982: }
0983:
0984: /** The infomation of the access object. */
0985: private static class AOInfo {
0986: private Class cls;
0987: private String name;
0988: private Class[] argTypes;
0989: private int flags;
0990:
0991: private AOInfo(Class cls, String name, Class[] argTypes,
0992: int flags) {
0993: this .cls = cls;
0994: this .name = name;
0995: this .argTypes = argTypes;
0996: this .flags = flags;
0997: }
0998:
0999: public int hashCode() {
1000: return cls.hashCode() + name.hashCode() + flags;
1001: }
1002:
1003: public boolean equals(Object o) {
1004: if (!(o instanceof AOInfo))
1005: return false;
1006:
1007: AOInfo aoi = (AOInfo) o;
1008: int len = argTypes != null ? argTypes.length : 0;
1009: int len2 = aoi.argTypes != null ? aoi.argTypes.length : 0;
1010: if (len != len2)
1011: return false;
1012:
1013: if (flags != aoi.flags || !cls.equals(aoi.cls)
1014: || !name.equals(aoi.name))
1015: return false;
1016:
1017: for (int j = 0; j < len; ++j)
1018: if (!Objects.equals(argTypes[j], aoi.argTypes[j]))
1019: return false;
1020: return true;
1021: }
1022: }
1023:
1024: /**
1025: * Gets the specified method by searching all methods including
1026: * <i>any</i> access control and any base class.
1027: * Note: you rarely need to call this metod. In most cases,
1028: * Class.getMethod, {@link #getCloseMethod}, and
1029: * {@link #getMethodInPublic} are what you need.
1030: *
1031: * <p>The search sequence is: this class's methods, and then
1032: * the superclass's methods.
1033: *
1034: * <p>Note: public methods don't be treated different. If the caller
1035: * wants to search public methods first, it has to call Class.getMethod
1036: * first.
1037: *
1038: * @param cls the class to search
1039: * @param name the method name
1040: * @param argTypes the parameter array of types
1041: * @return the Method object
1042: * @exception NoSuchMethodException if a matching method is not found.
1043: * @exception SecurityException if access to the information is denied.
1044: * @see #getAccessibleObject(Class, String, Class[], int)
1045: * @see #getAnyField(Class, String)
1046: */
1047: public static final Method getAnyMethod(Class cls, String name,
1048: Class[] argTypes) throws NoSuchMethodException {
1049: try {
1050: return cls.getDeclaredMethod(name, argTypes);
1051: } catch (NoSuchMethodException ex) {
1052: final Class[] clses = cls.getInterfaces();
1053: for (int j = 0; j < clses.length; ++j)
1054: try {
1055: return getAnyMethod(clses[j], name, argTypes);
1056: } catch (NoSuchMethodException e2) { //ignore it
1057: }
1058:
1059: cls = cls.getSuperclass();
1060: if (cls == null)
1061: throw ex;
1062: return getAnyMethod(cls, name, argTypes);
1063: }
1064: }
1065:
1066: /**
1067: * Gets the specified field by searching all fields including
1068: * any access control and any base class.
1069: * The search sequence is: this class's fields, and then
1070: * the superclass's fields.
1071: *
1072: * <p>Note: public fields don't be treated different. If the caller
1073: * wants to search public fields first, it has to call Class.getField
1074: * first.
1075: *
1076: * @param cls the class to search
1077: * @param name the field name
1078: * @return the Field object
1079: * @exception NoSuchFieldException if a matching field is not found.
1080: * @exception SecurityException if access to the information is denied.
1081: * @see #getAccessibleObject(Class, String, Class[], int)
1082: * @see #getAnyMethod(Class, String, Class[])
1083: */
1084: public static final Field getAnyField(Class cls, String name)
1085: throws NoSuchFieldException {
1086: for (;;) {
1087: try {
1088: return cls.getDeclaredField(name);
1089: } catch (NoSuchFieldException ex) {
1090: cls = cls.getSuperclass();
1091: if (cls == null)
1092: throw ex;
1093: }
1094: }
1095: }
1096:
1097: /**
1098: * Searches thru each element of the specified array of classes, and
1099: * returns classes that are super-classes (or equal) of
1100: * the sepcified class.
1101: *
1102: * @param cls the specified class; null is not allowed
1103: * @param clsToCheck the class array to check; null is acceptable
1104: * @return a subset of clsToCheck that are super-class of cls;
1105: * null if no one qualified
1106: */
1107: public static final Class[] getSuperClasses(Class cls,
1108: Class[] clsToCheck) {
1109: if (clsToCheck != null) {
1110: int[] hits = new int[clsToCheck.length];
1111: int no = 0;
1112: for (int j = 0; j < clsToCheck.length; ++j)
1113: if (clsToCheck[j].isAssignableFrom(cls))
1114: hits[no++] = j;
1115:
1116: if (no != clsToCheck.length) {
1117: if (no == 0)
1118: return null;
1119: Class[] exc = new Class[no];
1120: for (int j = 0; j < no; ++j)
1121: exc[j] = clsToCheck[hits[j]];
1122: return exc;
1123: }
1124: }
1125: return clsToCheck;
1126: }
1127:
1128: /**
1129: * Check whether the specified class is a primitive or a primitive wrapper.
1130: */
1131: public static final boolean isPrimitiveWrapper(Class cls) {
1132: return Objects.equals(cls.getPackage(), Boolean.class
1133: .getPackage())
1134: && (cls.equals(Boolean.class) || cls.equals(Byte.class)
1135: || cls.equals(Character.class)
1136: || cls.equals(Double.class)
1137: || cls.equals(Float.class)
1138: || cls.equals(Integer.class)
1139: || cls.equals(Long.class) || cls
1140: .equals(Short.class));
1141: }
1142:
1143: /** Checks whether the specified class is a numeric class.
1144: *
1145: * @param extend whether to consider Date, char, boolean, Character
1146: * and Boolean as a numeric object.
1147: */
1148: public static final boolean isNumeric(Class cls, boolean extend) {
1149: if (cls.isPrimitive())
1150: return extend
1151: || (!cls.equals(char.class) && !cls
1152: .equals(boolean.class));
1153:
1154: if (Number.class.isAssignableFrom(cls))
1155: return true;
1156:
1157: return extend
1158: && (cls.equals(Date.class) || cls.equals(Boolean.class) || cls
1159: .equals(Character.class));
1160: }
1161:
1162: /** Converts an object to the specified class.
1163: * It is the same as coerce(cls, val, true).
1164: *
1165: * <p>Future: use org.apache.commons.el.Coercions
1166: *
1167: * @param val the value.
1168: * @exception ClassCastException if failed to convert
1169: * @see #coerce(Class, Object, boolean)
1170: */
1171: public static Object coerce(Class cls, Object val)
1172: throws ClassCastException {
1173: if (cls.isInstance(val))
1174: return val;
1175:
1176: if (String.class == cls) {
1177: return Objects.toString(val);
1178: } else if (BigDecimal.class == cls) {
1179: if (val == null) {
1180: return null;
1181: } else if (val instanceof Double) {
1182: return new BigDecimal(((Double) val).doubleValue());
1183: } else if (val instanceof Float) {
1184: return new BigDecimal(((Float) val).doubleValue());
1185: } else if (val instanceof BigInteger) {
1186: return new BigDecimal((BigInteger) val);
1187: } else if (val instanceof Number) {
1188: return BigDecimals.toBigDecimal(((Number) val)
1189: .intValue());
1190: } else if (val instanceof String) {
1191: return new BigDecimal((String) val);
1192: } else if (val instanceof Date) {
1193: return new BigDecimal(((Date) val).getTime());
1194: }
1195: } else if (Integer.class == cls || int.class == cls) {
1196: if (val == null) {
1197: return Integer.class == cls ? null
1198: : Objects.ZERO_INTEGER;
1199: } else if (val instanceof Integer) { //int.class
1200: return val;
1201: } else if (val instanceof Number) {
1202: return new Integer(((Number) val).intValue());
1203: } else if (val instanceof String) {
1204: return new Integer((String) val);
1205: }
1206: } else if (Boolean.class == cls || boolean.class == cls) {
1207: if (val == null) {
1208: return Boolean.class == cls ? null : Boolean.FALSE;
1209: } else if (val instanceof Boolean) { //boolean.class
1210: return val;
1211: } else if (val instanceof String) {
1212: return Boolean.valueOf((String) val);
1213: } else if (val instanceof BigDecimal) {
1214: return Boolean
1215: .valueOf(((BigDecimal) val).signum() != 0);
1216: } else if (val instanceof BigInteger) {
1217: return Boolean
1218: .valueOf(((BigInteger) val).signum() != 0);
1219: } else if (val instanceof Number) {
1220: return Boolean.valueOf(((Number) val).intValue() != 0);
1221: } else {
1222: return Boolean.TRUE; //non-null is true
1223: }
1224: } else if (Short.class == cls || short.class == cls) {
1225: if (val == null) {
1226: return Short.class == cls ? null : Objects.ZERO_SHORT;
1227: } else if (val instanceof Short) { //short.class
1228: return val;
1229: } else if (val instanceof Number) {
1230: return new Short(((Number) val).shortValue());
1231: } else if (val instanceof String) {
1232: return new Short((String) val);
1233: }
1234: } else if (Long.class == cls || long.class == cls) {
1235: if (val == null) {
1236: return Long.class == cls ? null : Objects.ZERO_LONG;
1237: } else if (val instanceof Long) { //long.class
1238: return val;
1239: } else if (val instanceof Number) {
1240: return new Long(((Number) val).longValue());
1241: } else if (val instanceof String) {
1242: return new Long((String) val);
1243: } else if (val instanceof Date) {
1244: return new Long(((Date) val).getTime());
1245: }
1246: } else if (Double.class == cls || double.class == cls) {
1247: if (val == null) {
1248: return Double.class == cls ? null : Objects.ZERO_DOUBLE;
1249: } else if (val instanceof Double) { //double.class
1250: return val;
1251: } else if (val instanceof Number) {
1252: return new Double(((Number) val).doubleValue());
1253: } else if (val instanceof String) {
1254: return new Double((String) val);
1255: } else if (val instanceof Date) {
1256: return new Double(((Date) val).getTime());
1257: }
1258: } else if (BigInteger.class == cls) {
1259: if (val == null) {
1260: return null;
1261: } else if (val instanceof Integer) {
1262: return BigIntegers.toBigInteger((Integer) val);
1263: } else if (val instanceof Short) {
1264: return BigIntegers.toBigInteger((Short) val);
1265: } else if (val instanceof Byte) {
1266: return BigIntegers.toBigInteger((Byte) val);
1267: } else if (val instanceof Number) {
1268: return BigIntegers.toBigInteger(((Number) val)
1269: .longValue());
1270: } else if (val instanceof String) {
1271: return new BigInteger((String) val);
1272: } else if (val instanceof Date) {
1273: return BigIntegers.toBigInteger(((Date) val).getTime());
1274: }
1275: } else if (Float.class == cls || float.class == cls) {
1276: if (val == null) {
1277: return Float.class == cls ? null : Objects.ZERO_FLOAT;
1278: } else if (val instanceof Float) { //float.class
1279: return val;
1280: } else if (val instanceof Number) {
1281: return new Float(((Number) val).floatValue());
1282: } else if (val instanceof String) {
1283: return new Float((String) val);
1284: } else if (val instanceof Date) {
1285: return new Float(((Date) val).getTime());
1286: }
1287: } else if (Byte.class == cls || byte.class == cls) {
1288: if (val == null) {
1289: return Byte.class == cls ? null : Objects.ZERO_BYTE;
1290: } else if (val instanceof Byte) { //byte.class
1291: return val;
1292: } else if (val instanceof Number) {
1293: return new Byte(((Number) val).byteValue());
1294: } else if (val instanceof String) {
1295: return new Byte((String) val);
1296: }
1297: } else if (Character.class == cls || char.class == cls) {
1298: if (val == null) {
1299: return Character.class == cls ? null
1300: : Objects.NULL_CHARACTER;
1301: } else if (val instanceof Character) { //character.class
1302: return val;
1303: } else if (val instanceof Number) {
1304: return new Character((char) ((Number) val).shortValue());
1305: } else if (val instanceof String) {
1306: final String s = (String) val;
1307: return s.length() > 0 ? new Character(s.charAt(0))
1308: : Objects.NULL_CHARACTER;
1309: }
1310: } else if (Date.class == cls) {
1311: if (val == null) {
1312: return null;
1313: } else if (val instanceof Number) {
1314: return new Date(((Number) val).longValue());
1315: }
1316: } else if (Number.class == cls) {
1317: if (val == null) {
1318: return null;
1319: } else if (val instanceof String) {
1320: return new BigDecimal((String) val);
1321: } else if (val instanceof Date) {
1322: return new BigDecimal(((Date) val).getTime());
1323: }
1324: } else {
1325: if (val == null) {
1326: return null;
1327: } else {
1328: try {
1329: return cls.newInstance();
1330: } catch (Exception ex) {
1331: final ClassCastException t = new ClassCastException(
1332: Messages
1333: .get(
1334: MCommon.CLASS_NOT_COMPATIABLE,
1335: new Object[] {
1336: val.getClass(), cls }));
1337: t.initCause(ex);
1338: throw t;
1339: }
1340: }
1341: }
1342:
1343: throw new ClassCastException(Messages.get(
1344: MCommon.CLASS_NOT_COMPATIABLE, new Object[] {
1345: val != null ? val + "("
1346: + val.getClass().getName() + ")"
1347: : "null", cls }));
1348: }
1349:
1350: /** Converts to the specified type.
1351: *
1352: * @param nullable whether the result could be null.
1353: * If false, 0 is used for number, the default constructor is used
1354: * for others. {@link #coerce(Class, Object)} is a special case that
1355: * is equivalent to nullable=true.
1356: * @exception ClassCastException if failed to convert
1357: */
1358: public static Object coerce(Class cls, Object val, boolean nullable)
1359: throws ClassCastException {
1360: if (nullable || val != null)
1361: return coerce(cls, val);
1362:
1363: if (BigDecimal.class == cls) {
1364: return Objects.ZERO_BIG_DECIMAL;
1365: } else if (Integer.class == cls || int.class == cls) {
1366: return Objects.ZERO_INTEGER;
1367: } else if (Boolean.class == cls || boolean.class == cls) {
1368: return Boolean.FALSE;
1369: } else if (Short.class == cls || short.class == cls) {
1370: return Objects.ZERO_SHORT;
1371: } else if (Long.class == cls || long.class == cls) {
1372: return Objects.ZERO_LONG;
1373: } else if (Double.class == cls || double.class == cls) {
1374: return Objects.ZERO_DOUBLE;
1375: } else if (Byte.class == cls || byte.class == cls) {
1376: return Objects.ZERO_BYTE;
1377: } else if (BigInteger.class == cls) {
1378: return Objects.ZERO_BIG_INTEGER;
1379: } else if (Float.class == cls || float.class == cls) {
1380: return Objects.ZERO_FLOAT;
1381: } else if (Character.class == cls || char.class == cls) {
1382: return Objects.NULL_CHARACTER;
1383: } else {
1384: try {
1385: return cls.newInstance();
1386: } catch (Exception ex) {
1387: final ClassCastException t = new ClassCastException(
1388: Messages.get(MCommon.CLASS_NOT_COMPATIABLE,
1389: new Object[] { "null", cls }));
1390: t.initCause(ex);
1391: throw t;
1392: }
1393: }
1394: }
1395: }
|