* @param m The method to find types for.
     * @return Array of parameter types for the given method.
     */
    public static Class[] findParameterTypes(Class type, Method m)
    {
        Type[] genTypes = m.getGenericParameterTypes();
        Class[] types = new Class[genTypes.length];;
        boolean noGenericParameter = true;
        for (int i=0; i < genTypes.length; i++)
        {
            if (Class.class.isInstance(genTypes[i]))
            {
                types[i] = (Class) genTypes[i];
                continue;
            }
            noGenericParameter = false;
            break;
        }
        if (noGenericParameter)
        {
            return types;
        }

        if (type == null || !isJdk15())
        {
            return getParameterTypes(m);
        }

        final Type typeGenericSuperclass = type.getGenericSuperclass();
        if (typeGenericSuperclass == null
            || !ParameterizedType.class.isInstance(typeGenericSuperclass)
            || m.getDeclaringClass().getTypeParameters() == null)
        {
            return getParameterTypes(m);
        }

        if ((types = (Class[]) _genericMethodParameterTypesCache.get(m)) != null)
        {
            ParameterizedType genericSuperclass = (ParameterizedType) typeGenericSuperclass;
            if (Arrays.equals(types, genericSuperclass.getActualTypeArguments())) {
                return types;
            }
        }

        ParameterizedType param = (ParameterizedType)typeGenericSuperclass;
        TypeVariable[] declaredTypes = m.getDeclaringClass().getTypeParameters();

        types = new Class[genTypes.length];

        for (int i=0; i < genTypes.length; i++)
        {
            TypeVariable paramType = null;

            if (TypeVariable.class.isInstance(genTypes[i]))
            {
                paramType = (TypeVariable)genTypes[i];
            } else if (GenericArrayType.class.isInstance(genTypes[i]))
            {
                paramType = (TypeVariable) ((GenericArrayType)genTypes[i]).getGenericComponentType();
            }
            else if (ParameterizedType.class.isInstance(genTypes[i]))
            {
                 types[i] = (Class) ((ParameterizedType) genTypes[i]).getRawType();
                 continue;
            } else if (Class.class.isInstance(genTypes[i]))
            {
                types[i] = (Class) genTypes[i];
                continue;
            }

            Class resolved = resolveType(param, paramType, declaredTypes);

            if (resolved != null)
            {
                if (GenericArrayType.class.isInstance(genTypes[i]))
                {
                    resolved = Array.newInstance(resolved, 0).getClass();
                }

                types[i] = resolved;
                continue;
            }

            types[i] = m.getParameterTypes()[i];
        }

        synchronized (_genericMethodParameterTypesCache)
        {
            _genericMethodParameterTypesCache.put(m, types);
        }

        return types;
    }