/**
 * Copyright 2010 55 Minutes (http://www.55minutes.com)
 *
 * 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.
 */

package fiftyfive.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * Helpers for reflection tasks used internally by the 55 Minutes
 * Wicket library. Unlike the standard Java reflection methods,
 * these helpers do not throw checked exceptions.
 *
 * @author Matt Brictson
 */
public class ReflectUtils
{
    /**
     * Returns a method with the given name from the specified class. The
     * method must have zero arguments.
     *
     * @throws IllegalArgumentException if no method could be found
     */
    public static Method getZeroArgMethod(Class cls, String methodName)
    {
        Assert.notNull(cls, "cls cannot be null");
        Assert.notNull(methodName, "methodName cannot be null");
        
        // First check for method using getMethod()
        Method method = null;
        try
        {
            method = cls.getMethod(methodName, new Class[0]);
        }
        catch(NoSuchMethodException ignore) {}
        
        // If that fails, use getDeclaredMethod() going up the class hierarchy
        Class sup = cls;
        while(null == method && sup != null)
        {
            try
            {
                method = sup.getDeclaredMethod(methodName, new Class[0]);
            }
            catch(NoSuchMethodException ignore) {}
            sup = sup.getSuperclass();
        }
        
        // Last resort: throw IllegalArgumentException
        if(method == null)
        {
            throw new IllegalArgumentException(
                "Cannot find \"" + methodName + "\" method on : " + cls
            );
        }
        return method;
    }
    
    /**
     * Executes the specified method on the given bean. The method must exist
     * and require zero arguments.
     * @return The return value of the method, if any
     * @throws IllegalArgumentException if the method does not exist
     * @throws RuntimeException if the invocation fails
     */
    public static Object invokeZeroArgMethod(Object bean, String methodName)
    {
        Method method = getZeroArgMethod(bean.getClass(), methodName);

        // Ensure we can invoke even if method or class is not public
        method.setAccessible(true);

        Throwable cause = null;
        try
        {
            return method.invoke(bean);
        }
        catch(InvocationTargetException ite)
        {
            cause = ite.getCause();
        }
        catch(Exception e)
        {
            cause = e;
        }
        if(cause instanceof RuntimeException)
        {
            throw (RuntimeException) cause;
        }
        throw new RuntimeException(cause);
    }
    
    /**
     * This class is not meant to be constructed.
     */
    private ReflectUtils()
    {
    }
}

@@ -640,16 +640,48 @@
 .util;%0A%0A
+import java.lang.reflect.Field;%0A
 import j
@@ -760,43 +760,8 @@
 hod;
-%0Aimport java.lang.reflect.Modifier;
 %0A%0A/*
@@ -3295,36 +3295,2097 @@
 n(cause);%0A    %7D%0A
+%0A
     
+/**%0A     * Returns a field with the given name from the specified class.%0A     *%0A     * @throws IllegalArgumentException if no matching field could be found%0A     */%0A    public static Field getField(Class cls, String fieldName)%0A    %7B%0A        Assert.notNull(cls, %22cls cannot be null%22);%0A        Assert.notNull(fieldName, %22fieldName cannot be null%22);%0A        %0A        // First check for public field using getField()%0A        Field field = null;%0A        try%0A        %7B%0A            field = cls.getField(fieldName);%0A        %7D%0A        catch(NoSuchFieldException ignore) %7B%7D%0A        %0A        // If that fails, use getDeclaredField() going up the class hierarchy%0A        Class sup = cls;%0A        while(null == field && sup != null)%0A        %7B%0A            try%0A            %7B%0A                field = sup.getDeclaredField(fieldName);%0A            %7D%0A            catch(NoSuchFieldException ignore) %7B%7D%0A            sup = sup.getSuperclass();%0A        %7D%0A        %0A        // Last resort: throw IllegalArgumentException%0A        if(field == null)%0A        %7B%0A            throw new IllegalArgumentException(%0A                %22Cannot find %5C%22%22 + fieldName + %22%5C%22 method on : %22 + cls%0A            );%0A        %7D%0A        return field;%0A    %7D%0A    %0A    /**%0A     * Reads the specified field from the given bean. The field must exist,%0A     * but can be private.%0A     * @return The value of the field%0A     * @throws IllegalArgumentException if the field does not exist%0A     * @throws RuntimeException if reflection otherwise fails%0A     */%0A    public static Object readField(Object bean, String fieldName)%0A    %7B%0A        Field field = getField(bean.getClass(), fieldName);%0A%0A        // Ensure we can access even if field or class is not public%0A        field.setAccessible(true);%0A%0A        Throwable cause = null;%0A        try%0A        %7B%0A            return field.get(bean);%0A        %7D%0A        catch(Exception e)%0A        %7B%0A            cause = e;%0A        %7D%0A        if(cause instanceof RuntimeException)%0A        %7B%0A            throw (RuntimeException) cause;%0A        %7D%0A        throw new RuntimeException(cause);%0A    %7D%0A
 %0A    /**%0A     * 

Add field-level reflection utils.