Java tutorial
/* * Copyright 2007-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Project: JGentleFramework */ package org.jgentleframework.utils; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.aopalliance.reflect.Metadata; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jgentleframework.core.handling.DefinitionManager; import org.jgentleframework.reflection.metadata.AnnotationMetadata; import org.jgentleframework.reflection.metadata.MetaDataFactory; import sun.reflect.FieldAccessor; import sun.reflect.ReflectionFactory; /** * Provides some of static methods in order to execute common reflect * operations. * <p> * Mainly for use within the framework, but also useful for application code. * * @author LE QUOC CHUNG - mailto: <a * href="mailto:skydunkpro@yahoo.com">skydunkpro@yahoo.com</a> * @date Aug 29, 2007 */ public final class ReflectUtils { /** The Constant log. */ private final static Log log = LogFactory.getLog(ReflectUtils.class); /** * Creates {@link AnnotationMetadata} object. * * @param annos * annotation instance need to be create to * {@link AnnotationMetadata} * @param container * the parrent {@link AnnotationMetadata} of returned * {@link AnnotationMetadata} * @param definitionManager * the {@link DefinitionManager} instance * @return AnnotationMetadata * @throws InvocationTargetException * the invocation target exception * @throws IllegalAccessException * the illegal access exception * @throws IllegalArgumentException * the illegal argument exception */ public static AnnotationMetadata buildAnnoMeta(Annotation annos, AnnotationMetadata container, DefinitionManager definitionManager) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { AnnotationMetadata thisMeta = null; Class<?> clazz = annos.annotationType(); Method[] methods = clazz.getDeclaredMethods(); thisMeta = MetaDataFactory.createAnnotationMetadata(clazz, annos, container, clazz.toString()); if (methods.length > 0) { for (Method obj : methods) { Object value = null; obj.setAccessible(true); value = obj.invoke(annos); Metadata part = null; part = MetaDataFactory.createMetaData(obj.getName(), value); /* * ?a list sub annotationMetadata va c to vo trong * annotationMetadata hin hnh */ thisMeta.putMetaData(part); } } /* * add annotationMetadata vo container (annotationMetadata cha ch n) */ container.putMetaData(thisMeta); return thisMeta; } /** * Creates an object instance. * * @param clazz * the object class type * @param args * the arguments of the constructor need to be use to instantiate * bean. instance. * @return tr v? i tng Object va c khi to. */ @SuppressWarnings("unchecked") public static <T> T createInstance(Class<T> clazz, Object... args) { T result = null; try { Constructor<T> constructor = null; if (args == null) { constructor = clazz.getDeclaredConstructor(); } else { List<Class<?>> argsType = new ArrayList<Class<?>>(); for (Object arg : args) { argsType.add(arg.getClass()); } constructor = clazz.getDeclaredConstructor(argsType.toArray(new Class<?>[argsType.size()])); } constructor.setAccessible(true); result = args == null ? (T) constructor.newInstance() : constructor.newInstance(args); } catch (InstantiationException e) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } catch (IllegalAccessException e) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } catch (SecurityException e) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } catch (NoSuchMethodException e) { if (args != null) { for (Constructor<?> cons : clazz.getDeclaredConstructors()) { cons.setAccessible(true); try { result = (T) cons.newInstance(args); } catch (IllegalArgumentException e1) { continue; } catch (InstantiationException e1) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e1); } } catch (IllegalAccessException e1) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e1); } } catch (InvocationTargetException e1) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e1); } } } if (result == null) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } } else { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } } catch (IllegalArgumentException e) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } catch (InvocationTargetException e) { if (log.isFatalEnabled()) { log.fatal("Could not create instance basing on target class ['" + clazz + "']", e); } } return result; } /** * Returns <code>true</code> if two given {@link Field} are equalled. Two * {@link Field fields} are considered equal if and only if their names are * equalled and their declared types are equalled too. * * @param source * the source field * @param target * the target field * @return true, if two given field are equalled */ public static boolean equals(Field source, Field target) { if (!source.getType().equals(target.getType())) { return false; } if (!source.getName().equals(target.getName())) { return false; } return true; } /** * Returns <code>true</code> if two given {@link Method} are equalled. Two * {@link Method methods} are considered equal if and only if their names * are equalled and their declared parameter types are equalled too. * * @param source * the source method * @param target * the target method * @return true, if two given method are equalled */ public static boolean equals(Method source, Method target) { int check = 0; Class<?>[] sourceArgs; if (source.getName().equals(target.getName())) { check++; sourceArgs = source.getParameterTypes(); } else return false; if (source.getReturnType() != target.getReturnType()) return false; if (check != 0) { for (int i = 0; i < check; i++) { Class<?>[] targetArgs = target.getParameterTypes(); if (targetArgs.length != sourceArgs.length) { return false; } else { int matchesType = 0; for (int j = 0; j < sourceArgs.length; j++) { if (targetArgs[j].equals(sourceArgs[j])) { matchesType++; } } if (matchesType != sourceArgs.length) { return false; } } } } return true; } /** * Thc thi tr v? cc {@link Field} tng ng vi <code>object class</code> * cung cp tng ng. * <p> * <i>Method ny thc thi tng ng * {@link ReflectUtils#fields(String, Class, boolean)} vi</i> gi tr * boolean (<code>'superClass'</code>) <i>ch nh l <b>false</b></i>. ?i?u ny c ngha rng * danh sch tm kim s ch bao gm cc <code>fields</code> c khai bo * trong phm vi <code>Class</code> tng ng, khng bao gm * <code>superClass</code> ca Class ch nh . * <p> * Lu rng phng thc ny s ch tr v? cc * <code>non-static fields</code>. * <p> * - C th s dng <code>Regular Expression</code> ch nh tn * {@link Field} tr v?. * <p> * <b>EX:</b> * <p> * <code>field("str*")</code> s ch nh tr v? tt c cc {@link Field} * bt u vi chui "str" hoc * <p> * <code>field("?name")</code> s ch nh tr v? tt c cc {@link Field} * bt u vi 1 ch bt k v theo sau l chui 'name'. * * @param name * tn nh danh ca field * @param clazz * object class ch nh tng ng. * @return tr v? mt mng cc {@link Field} tng ng tm c nu c, nu * khng tr v? mt danh sch rng. */ public static Field[] fields(String name, Class<?> clazz) { return fields(name, clazz, false); } /** * Thc thi tr v? cc {@link Field} tng ng vi <code>object class</code> * cung cp tng ng. * <p> * Lu rng phng thc ny s ch tr v? cc * <code>non-static fields</code>. * <p> * - C th s dng <code>Regular Expression</code> ch nh tn * {@link Field} tr v?. * <p> * <b>EX:</b> * <p> * <code>field("str*")</code> s ch nh tr v? tt c cc {@link Field} * bt u vi chui "str" hoc * <p> * <code>field("?name")</code> s ch nh tr v? tt c cc {@link Field} * bt u vi 1 ch bt k v theo sau l chui "name". * * @param name * tn nh danh ca field * @param clazz * object class tng ng * @param superClass * nu ch nh l <b>true</b>, danh sch cc <code>fields</code> * tm kim s bao gm c cc <code>fields</code> c khai bo * bi <code>superClass</code> ca Class hin hnh. Ngc li, * nu ch nh l <b>false</b>, danh sch tm kim ch nm trong * phm vi cc <code>fields</code> c khai bo trong * <code>Class</code> tng ng. * @return tr v? mt mng cc {@link Field} tng ng tm c nu c, nu * khng tr v? mt danh sch rng. */ public static Field[] fields(String name, Class<?> clazz, boolean superClass) { List<Field> lst = new ArrayList<Field>(); Field[] fields = null; if (superClass) { fields = ReflectUtils.getDeclaredFields(clazz, false, true); } else { fields = clazz.getDeclaredFields(); } for (Field field : fields) { if (RegularToolkit.matches(name, field.getName())) { lst.add(field); } } return lst.toArray(new Field[lst.size()]); } /** * Returns the all declared fields. The fields are added to the end of the * given list and are guaranteed to be non-static. * * @param clazz * the given object class * @return an array containing all declared fields. */ public static Field[] getAllDeclaredFields(Class<?> clazz) { List<Field> result = new ArrayList<Field>(); result.addAll(Arrays.asList(getDeclaredFields(clazz, false, false))); return result.toArray(new Field[result.size()]); } /** * Returns the all declared methods. The methods are added to the end of the * given list and are guaranteed to be non-static. The returned methods will * be included all the methods occur in the given class, its superclass and * all its implemented interface. * * @param clazz * the given object class * @return an array containing all declared methods. */ public static Method[] getAllDeclaredMethods(Class<?> clazz) { List<Method> result = new ArrayList<Method>(); result.addAll(Arrays.asList(getDeclaredMethods(clazz, false, false))); Set<Class<?>> interfaces = getAllInterfaces(clazz, true); for (Class<?> interfaze : interfaces) { Method[] methods = getDeclaredMethods(interfaze, false, false); for (Method target : methods) { result.add(target); } } return result.toArray(new Method[result.size()]); } /** * Returns the all {@link Type Types} representing the interfaces * implemented by the class or interface represented by given object class. * * @param clazz * the given object class * @param superClass * if <b>true</b>, the result will includes all types of super * classes and super interfaces of given object class. * @return an {@link ArrayList} containing returned types if they exist, * otherwise, returns an empty {@link ArrayList}. */ public static List<Type> getAllGenericInterfaces(Class<?> clazz, boolean superClass) { Assertor.notNull(clazz); List<Type> result = new ArrayList<Type>(); for (Type type : clazz.getGenericInterfaces()) { if (!result.contains(type)) { int i = 0; for (Type resultType : result) { if (resultType.toString().equals(type.toString())) { i++; } } if (i == 0) { result.add(type); } } } // Tm trn tt c cc interfaces ca clazz hin hnh Set<Class<?>> listInterfaces = ReflectUtils.getAllInterfaces(clazz, superClass); for (Class<?> interfaze : listInterfaces) { for (Type type : interfaze.getGenericInterfaces()) { if (!result.contains(type)) { int i = 0; for (Type resultType : result) { if (resultType.toString().equals(type.toString())) { i++; } } if (i == 0) { result.add(type); } } } } // Tm trn tt c cc superClass ca clazz hin hnh List<Class<?>> listClass = ReflectUtils.getAllSuperClass(clazz, false); for (Class<?> current : listClass) { for (Type type : current.getGenericInterfaces()) { if (!result.contains(type)) { int i = 0; for (Type resultType : result) { if (resultType.toString().equals(type.toString())) { i++; } } if (i == 0) { result.add(type); } } } } return result; } /** * Returns all interfaces implemented by the class or interface represented * by the given class. * <p> * <b>Note:</b> Each interface signature will only occur once, even if it is * implemented in multiple classes or interfaces. * * @param clazz * the given class * @param superClass * if specifies <code>true</code>, returning {@link Set} of * interfaces will be included all interfaces implemented by * super class of the given class, otherwise, if specifies * <code>false</code>, the returned interfaces will be found only * on the given class. * @return an {@link Set} of interfaces implemented by the given class. */ public static Set<Class<?>> getAllInterfaces(Class<?> clazz, boolean superClass) { Set<Class<?>> temp = new LinkedHashSet<Class<?>>(); temp.addAll(Arrays.asList(clazz.getInterfaces())); Set<Class<?>> result = new LinkedHashSet<Class<?>>(); while (temp.size() != 0) { for (Class<?> obj : temp) { if (!result.contains(obj)) { result.add(obj); } } Set<Class<?>> current = new LinkedHashSet<Class<?>>(); current.addAll(temp); temp.clear(); for (Class<?> obj : current) { temp.addAll(Arrays.asList(obj.getInterfaces())); } } if (superClass == true) { List<Class<?>> superClassList = ReflectUtils.getAllSuperClass(clazz, false); for (Class<?> scl : superClassList) { Set<Class<?>> sclInterfaces = ReflectUtils.getAllInterfaces(scl, false); for (Class<?> sclinterface : sclInterfaces) { if (!result.contains(sclinterface)) { result.add(sclinterface); } } } } return result; } /** * Returns all super class of the given class. * * @param clazz * the given object class. * @param includesObjectClass * if specifies <b>true</b>, the returned {@link List} will be * inclued {@link Object} class, otherwise, specifies * <b>false</b> * @return an {@link List} of {@link Class Classes} if they're existed, if * not, returns an empty {@link List}. */ public static List<Class<?>> getAllSuperClass(Class<?> clazz, boolean includesObjectClass) { List<Class<?>> result = new ArrayList<Class<?>>(); Class<?> temp = clazz.getSuperclass(); while (temp != null) { if (includesObjectClass == false) { if (temp == Object.class) { break; } } result.add(temp); temp = temp.getSuperclass(); } return result; } /** * Returns the object class types of the given objects. * * @param objects * a object or a set of objects need to be taken class type. * @return returns an array containing corresponding class types. */ public static Class<?>[] getClassTypeOf(Object... objects) { Assertor.notNull(objects); Class<?>[] result = new Class<?>[objects.length]; for (int i = 0; i < objects.length; i++) { Assertor.notNull(objects[i]); result[i] = objects[i].getClass(); } return result; } /** * Returns all {@link Field fields} occurs in the given class and its super * classes. Each field signature will only occur once, even if it occurs in * multiple classes and the returned array is only included non-static * fields. * * @param clazz * the given class * @return an array containing all desired fields if they exist, if not * return an empty array. */ public static Field[] getDeclaredFields(Class<?> clazz) { return getDeclaredFields(clazz, false, true); } /** * Returns all {@link Field fields} occurs in the given class and its super * classes. * * @param clazz * the given class * @param includeStatic * if specifies <b>true</b>, the returned array is only included * static fields, otherwise, if specifies <b>false</b>, only * non-static fields are returned. * @param non_multiple * if specifies <b>true</b>, each field signature will only occur * once, even if it occurs in multiple classes, otherwise, * specifies <b>false</b>. * @return an array containing all desired fields if they exist, if not * return an empty array. */ public static Field[] getDeclaredFields(Class<?> clazz, boolean includeStatic, boolean non_multiple) { List<Field> accum = new ArrayList<Field>(); while (clazz != null && clazz != Object.class) { Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { int modifiers = fields[i].getModifiers(); if (includeStatic == Modifier.isStatic(modifiers) && !accum.contains(fields[i])) { if (non_multiple) { int check = 0; for (Field field : accum) { if (equals(field, fields[i])) { check++; } } if (check == 0) accum.add(fields[i]); } else accum.add(fields[i]); } } clazz = clazz.getSuperclass(); } Field[] retvalue = new Field[accum.size()]; return (Field[]) accum.toArray(retvalue); } /** * Returns all {@link Method methods} occurs in the given class and its * super classes. Each method signature will only occur once, even if it * occurs in multiple classes and the returned array is only included * non-static methods. * * @param clazz * the given class * @return an array containing all desired methods if they exist, if not * return an empty array. */ public static Method[] getDeclaredMethods(Class<?> clazz) { return getDeclaredMethods(clazz, false, true); } /** * Returns all {@link Method methods} occurs in the given class and its * super classes. * * @param clazz * the given class * @param includeStatic * if specifies <b>true</b>, the returned array is only included * static methods, otherwise, if specifies <b>false</b>, only * non-static methods are returned. * @param non_multiple * if specifies <b>true</b>, each method signature will only * occur once, even if it occurs in multiple classes, otherwise, * specifies <b>false</b>. * @return an array containing all desired methods if they exist, if not * return an empty array. */ public static Method[] getDeclaredMethods(Class<?> clazz, boolean includeStatic, boolean non_multiple) { List<Method> accum = new ArrayList<Method>(); while (clazz != null && clazz != Object.class) { Method[] methods = clazz.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { int modifiers = methods[i].getModifiers(); if (includeStatic == Modifier.isStatic(modifiers) && !accum.contains(methods[i])) { if (non_multiple) { int check = 0; for (Method method : accum) { if (equals(method, methods[i])) { check++; } } if (check == 0) accum.add(methods[i]); } else accum.add(methods[i]); } } clazz = clazz.getSuperclass(); } Method[] retvalue = new Method[accum.size()]; return (Method[]) accum.toArray(retvalue); } /** * Returns the default {@link ClassLoader}. * * @return {@link ClassLoader} */ public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { if (log.isFatalEnabled()) { log.fatal("Cannot access thread context ClassLoader " + "- falling back to system class loader", ex); } } if (cl == null) { cl = ReflectUtils.class.getClassLoader(); } return cl; } /** * Returns the first <b>abstract</b> super class of the given class. * * @param clazz * the given class * @return returns the object class of the first abstract super class of the * given class if it exists, if not, reuturns <code>null</code> */ public static Class<?> getFirstAbstractSuperClass(Class<?> clazz) { Class<?> result = clazz.getSuperclass(); while (result != null) { if (!Modifier.isAbstract(result.getModifiers())) { result = result.getSuperclass(); } else { break; } } return result; } /** * Tm kim v tr v? field tng ng trong mt class ch nh. <br> * <br> * <b>Lu :</b> Hm s t ng tm trong <code>object class</code> ch * nh, nu khng c s tm tm tip trong cc <code>SuperClass</code> ca * n. * * @param cls * i tng <code>object class</code> truy vn * <code>field</code>. * @param name * tn ca field cn tm. * @return tr v? field tm c. * @throws NoSuchFieldException * nm ra ngoi l nu nh khng c field no trong object class * ch nh ng vi tn name cung cp. */ public static Field getSupportedField(Class<?> cls, String name) throws NoSuchFieldException { if (cls != null) { try { return cls.getDeclaredField(name); } catch (NoSuchFieldException e) { return getSupportedField(cls.getSuperclass(), name); } } else { throw new NoSuchFieldException("Could not find the field ['" + name + "'] !"); } } /** * Tr v? <code>declared method</code> c support trong <code>clazz</code> * c ch nh da trn tn <code>name</code> v <code>paramTypes</code>. * Nu <code>class</code> hin ti khng support Method cn tm th s tm * trong <code>SuperClass</code> ca <code>class</code> c ch nh, nu * nh khng tn ti bt k <code>Method</code> no tng ng, mt ngoi l * {@link NoSuchMethodException} s c nm ra. * * @param clazz * Class Object cn truy vn. * @param name * tn method cn truy vn. * @param paramTypes * mng array cc Class Object Type tham s truy?n ca method. * @return tr v? Method mun truy vn * @throws NoSuchMethodException * nm ra ngoi l ny nu nh khng tm thy bt k method no * tng ng c trong clazz hoc trong cc SuperClass ca n. */ public static Method getSupportedMethod(Class<?> clazz, String name, Class<?>[] paramTypes) throws NoSuchMethodException { if (clazz == null) { throw new NoSuchMethodException("Method '" + name + "' is not existed."); } try { return clazz.getDeclaredMethod(name, paramTypes); } catch (NoSuchMethodException ex) { return getSupportedMethod(clazz.getSuperclass(), name, paramTypes); } } /** * Invokes the given <code>method</code> basing on the given * <code>target object</code>. * * @param obj * the target object * @param methodName * the method name * @param paramTypes * the parameter types array * @param args * the arguments used for the method call * @param superBool * nu l <b>true</b> s truy tm phng thc trn * <code>Object Class</code> v c <code>SuperClass</code> ca * <code>object</code> ch nh tng ng , ngc li nu l * <b>false</b> s ch truy vn trn <code>Object Class</code> * ch nh. * @param noThrows * nu l <b>true</b> s khng nm ra <code>exception</code> nu * nh gp li trong lc thi hnh, ngc li nu l <b>false</b> * s nm ra ngoi l nu gp li trong lc thi hnh. Lu rng * tham s <code>noThrows</code> ch c hiu lc trn cc tin * trnh <code>reflect</code> lc <code>invoke method</code>, nu * bn thn <code>method</code> c <code>invoked</code> nm ra * <code>exception</code> th c ch nh t?ng minh * <code>noThrows</code> hay khng ?u khng c tc dng. * @return tr v? <code>Object</code> tr v? sau khi invoke method, nu * <code>method</code> cn triu g?i khng <code>return</code> th * kt qu tr v? s l <b>NULL</b>. * @throws NoSuchMethodException * the no such method exception * @throws IllegalAccessException * the illegal access exception * @throws InvocationTargetException * the invocation target exception * @throws IllegalArgumentException */ public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramTypes, Object[] args, boolean superBool, boolean noThrows) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Class<?> clazz = null; if (ReflectUtils.isAnnotation(obj)) { clazz = ((Annotation) obj).annotationType(); } clazz = obj.getClass(); /* * Kim tra thng tin hp l ca parameters */ if (paramTypes != null && args != null) { if (paramTypes.length != args.length) { throw new IllegalArgumentException("Parameter is invalid ! "); } } try { if (superBool == true) { Method method = ReflectUtils.getSupportedMethod(clazz, methodName, paramTypes); method.setAccessible(true); return method.invoke(obj, args); } else { return clazz.getDeclaredMethod(methodName, paramTypes).invoke(obj, args); } } catch (NoSuchMethodException ex) { if (noThrows == false) { throw new NoSuchMethodException(clazz.getName() + " does not support method " + methodName); } } catch (IllegalAccessException ex) { if (noThrows == false) { throw new IllegalAccessException( "Insufficient access permissions to call" + methodName + " in class " + clazz.getName()); } } catch (InvocationTargetException ex) { throw ex; } return null; } /** * Returns <b>true</b> if the given object is an annotation implementation. * * @param obj * the given object need to be tested. * @return <b>true</b> if the given object is an annotation implementation, * <b>false</b> otherwise. */ public static boolean isAnnotation(Object obj) { Assertor.notNull(obj); try { Annotation.class.cast(obj); } catch (RuntimeException e) { return false; } return true; } /** * Returns <b>true</b> if given list of objects are annotation * implementations. If has just any object class can not be casted, returns * <b>false</b>. * * @param objs * the list of objects need to be test. */ public static boolean isAnnotation(Object... objs) { Assertor.notNull((Object[]) objs); if (objs.length == 0) { Assertor.throwRunTimeException("The list of annotation instances need to be casted must not be empty!"); } boolean result = true; for (Object o : objs) { result = isAnnotation(o); if (result == false) break; } return result; } /** * Returns <b>true</b> if given object can be casted to the class or * interface type represents by the given Class object. Otherwise returns * <b>false</b>. * * @param clazz * the object class * @param obj * the object need to be checked. * @return true, if checks if is cast */ public static boolean isCast(Class<?> clazz, Object obj) { return clazz.isInstance(obj); } /** * Returns <b>true</b> if given object can be casted to all object classes * of given list. If has just any object class can not be casted, returns * <b>false</b>. * * @param obj * the object need to be checked. * @param classes * the list of classes * @return true, if checks if is cast */ public static boolean isCast(Object obj, Class<?>... classes) { Assertor.notNull((Object[]) classes); if (classes.length == 0) { Assertor.throwRunTimeException("The list of classes need to be casted must not be empty!"); } boolean result = true; for (Class<?> clazz : classes) { result = clazz.isInstance(obj); if (result == false) break; } return result; } /** * Returns <b>true</b> if given object is a {@link Class}, <b>false</b> * otherwise. * * @param obj * given object need to be tested * @return true, if checks if is class */ public static boolean isClass(Object obj) { return Class.class.isInstance(obj); } /** * Returns <b>true</b> if given object is a {@link Constructor}, * <b>false</b> otherwise. * * @param obj * given object need to be tested * @return true, if checks if is constructor */ public static boolean isConstructor(Object obj) { return isCast(Constructor.class, obj); } /** * Determine whether the given method explicitly declares the given * exception or one of its superclasses, which means that an exception of * that type can be propagated as-is within a reflective invocation. * * @param method * <the declaring method * @param exceptionType * the exception to throw * @return <code>true</code> if the exception can be thrown as-is; * <code>false</code> if it needs to be wrapped */ @SuppressWarnings("unchecked") public static boolean isDeclaredException(Method method, Class<? extends Throwable> exceptionType) { Assertor.notNull(method, "Method [" + method + "] must not be null."); Class<? extends Throwable>[] declaredExceptions = (Class<? extends Throwable>[]) method.getExceptionTypes(); for (int i = 0; i < declaredExceptions.length; i++) { Class<? extends Throwable> declaredException = declaredExceptions[i]; if (declaredException.isAssignableFrom(exceptionType)) { return true; } } return false; } /** * Returns <b>true</b> if given object is a {@link Field}, <b>false</b> * otherwise. * * @param obj * given object need to be tested * @return true, if checks if is field */ public static boolean isField(Object obj) { Assertor.notNull(obj); if (obj.getClass().equals(Field.class)) { return true; } return false; } /** * Returns <b>true</b> if given object is a interface, <b>false</b> * otherwise. * * @param obj * given object need to be tested * @return true, if checks if is interface */ public static boolean isInterface(Object obj) { Assertor.notNull(obj); return obj.getClass().isInterface(); } /** * Returns <b>true</b> if given object is a {@link Method}, <b>false</b> * otherwise. * * @param obj * given object need to be tested * @return true, if checks if is method */ public static boolean isMethod(Object obj) { Assertor.notNull(obj); if (obj.getClass().equals(Method.class)) { return true; } return false; } /** * Returns <b>true</b> if given {@link Field} is <b>public, static, * final</b>, otherwise returns <b>false</b>. * * @param field * given {@link Field} need to be tested * @return true, if checks if is public static final */ public static boolean isPublicStaticFinal(Field field) { int modifiers = field.getModifiers(); return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers); } /** * Returns <b>true</b> if given {@link Method} is <b>public, static, * final</b>, otherwise returns <b>false</b>. * * @param method * given {@link Method} need to be tested * @return true, if checks if is public static final */ public static boolean isPublicStaticFinal(Method method) { int modifiers = method.getModifiers(); return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)); } /** * Phng thc s kim tra xem <code>annotation</code> ch nh c * {@link Target} tng ng hp l vi i tng <code>object</code> hay * khng (i tng <code>object</code> c th l bt k thc th ch nh * no cho php annotate annotation nh * <code>Class, Interface, Annotation, Enum, Method, Field, Constructor, ...</code> * ) * * @param annotation * i tng <code>annotation</code> cn kim tra. * @param obj * i tng <code>object</code> cn kim tra * @return tr v? <b>true</b> nu c, nu khng tr v? <b>false</b>. */ public static boolean isValidTarget(Annotation annotation, Object obj) { if (annotation.annotationType().isAnnotationPresent(Target.class)) { Target target = annotation.annotationType().getAnnotation(Target.class); if (obj.getClass().isAnnotation()) { if (!Arrays.asList(target.value()).contains(ElementType.TYPE) || !Arrays.asList(target.value()).contains(ElementType.ANNOTATION_TYPE)) { return false; } } else if (ReflectUtils.isCast(Constructor.class, obj)) { if (!Arrays.asList(target.value()).contains(ElementType.CONSTRUCTOR)) { return false; } } else if (ReflectUtils.isField(obj)) { if (!Arrays.asList(target.value()).contains(ElementType.FIELD)) { return false; } } else if (ReflectUtils.isMethod(obj)) { if (!Arrays.asList(target.value()).contains(ElementType.METHOD)) { return false; } } else if (ReflectUtils.isClass(obj) || ReflectUtils.isInterface(obj)) { if (!Arrays.asList(target.value()).contains(ElementType.TYPE)) { return false; } } else { if (!obj.getClass().isAnnotation() && !ReflectUtils.isCast(Constructor.class, obj) && !ReflectUtils.isField(obj) && !ReflectUtils.isMethod(obj.getClass()) && !ReflectUtils.isClass(obj) && !ReflectUtils.isInterface(obj)) { return false; } } } return true; } /** * Make the given constructor accessible, explicitly setting it accessible * if necessary. The <code>setAccessible(true)</code> method is only called * when actually necessary, to avoid unnecessary conflicts with a JVM * SecurityManager (if active). * * @param ctor * the constructor to make accessible * @see java.lang.reflect.Constructor#setAccessible(boolean) */ public static void makeAccessible(Constructor<?> ctor) { if (!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) { ctor.setAccessible(true); } } /** * Make the given field accessible, explicitly setting it accessible if * necessary. The <code>setAccessible(true)</code> method is only called * when actually necessary, to avoid unnecessary conflicts with a JVM * SecurityManager (if active). * * @param field * the field to make accessible * @see java.lang.reflect.Field#setAccessible(boolean) */ public static void makeAccessible(Field field) { if (!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())) { field.setAccessible(true); } } /** * Make the given method accessible, explicitly setting it accessible if * necessary. The <code>setAccessible(true)</code> method is only called * when actually necessary, to avoid unnecessary conflicts with a JVM * SecurityManager (if active). * * @param method * the method to make accessible * @see java.lang.reflect.Method#setAccessible(boolean) */ public static void makeAccessible(Method method) { if (!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) { method.setAccessible(true); } } /** * Returns an array containing method objects that corresponds to the given * name (or regular expression pattern of name) * <p> * <b>Note:</b> * <p> * - This method only returns <code>non-static methods</code>.<br> * - This method result is the same as * {@link #methods(String, Class, boolean)} according to * <code>superClass</code> argument is <code>false</code> * <p> * - <code>Regular expression</code> can be used in order to specify a set * of returned methods. * <p> * <b>EX:</b> * <p> * <code>methods("set*")</code> shall specify to return all of setter * methods. * * @param name * the name (or regular expression pattern) of method or a set of * methods. * @param clazz * the declaring class * @return an array containing method objects if they exist, if not, return * an empty array. */ public static Method[] methods(String name, Class<?> clazz) { return methods(name, clazz, false); } /** * Returns an array containing method objects that corresponds to the given * name (or regular expression pattern of name) * <p> * <b>Note:</b> * <p> * - This method only returns <code>non-static methods</code>. * <p> * - <code>Regular expression</code> can be used in order to specify a set * of returned methods. * <p> * <b>EX:</b> * <p> * <code>method("set*")</code> shall specify to return all of setter * methods. * * @param name * the name (or regular expression pattern) of method or a set of * methods. * @param clazz * the declaring class * @param superClass * if is specified to be <b>true</b>, the returned method list * includes method objects are declared in current derived class * and also in super class of it. Otherwise, if is specified to * be <b>false</b>, the returned method list only includes method * objects are declared in current derived class, exclude super * classes of it. * @return an array containing method objects if they exist, if not, return * an empty array. */ public static Method[] methods(String name, Class<?> clazz, boolean superClass) { List<Method> lst = new ArrayList<Method>(); Method[] methods = null; if (superClass) { methods = ReflectUtils.getDeclaredMethods(clazz, false, true); } else { methods = clazz.getDeclaredMethods(); } for (Method method : methods) { if (RegularToolkit.matches(name, method.getName())) { lst.add(method); } } return lst.toArray(new Method[lst.size()]); } /** The Constant MODIFIERS_FIELD. */ private static final String MODIFIERS_FIELD = "modifiers"; /** The Constant reflection. */ private static final ReflectionFactory reflection = ReflectionFactory.getReflectionFactory(); /** * Sets new value to static final field. * <p> * <b>Note</b>: this method only run on Sun JDK * * @param field * the field * @param value * the new value * @throws NoSuchFieldException * the no such field exception * @throws IllegalAccessException * the illegal access exception */ public static void setStaticFinalField(Field field, Object value) throws NoSuchFieldException, IllegalAccessException { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField(MODIFIERS_FIELD); modifiersField.setAccessible(true); int modifiers = modifiersField.getInt(field); modifiers &= ~Modifier.FINAL; modifiersField.setInt(field, modifiers); FieldAccessor fa = reflection.newFieldAccessor(field, false); fa.set(null, value); } }