All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.sugarcubes.cloner.ReflectionUtils Maven / Gradle / Ivy

/*
 * Copyright 2017-2023 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.
 */
package io.github.sugarcubes.cloner;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import static io.github.sugarcubes.cloner.ClonerExceptionUtils.replaceException;

/**
 * Shortcuts for Java Reflection API.
 *
 * @author Maxim Butov
 */
public class ReflectionUtils {

    /**
     * Checks the availability of the class in current class loader.
     *
     * @param className name of the class
     * @return {@code true} if class is available
     */
    public static boolean isClassAvailable(String className) {
        try {
            Class.forName(className);
            return true;
        }
        catch (ClassNotFoundException e) {
            return false;
        }
    }

    /**
     * Checks the availability of the method in the class.
     *
     * @param type class
     * @param methodName name of the method
     * @param parameterTypes parameter types
     * @return {@code true} if the method is available
     */
    public static boolean isMethodAvailable(Class type, String methodName, Class... parameterTypes) {
        try {
            type.getDeclaredMethod(methodName, parameterTypes);
            return true;
        }
        catch (NoSuchMethodException e) {
            return false;
        }
    }

    /**
     * Version of {@link Class#forName(String)} with unchecked exception.
     *
     * @param className class name
     * @param  type
     * @return {@link Class} instance
     */
    public static  Class classForName(String className) {
        return (Class) replaceException(() -> Class.forName(className));
    }

    /**
     * Returns accessible field.
     * Same as {@link Class#getDeclaredField(String)}.
     *
     * @param type {@link Class} instance
     * @param name field name
     * @return field
     */
    public static Field getField(Class type, String name) {
        return replaceException(() -> makeAccessible(type.getDeclaredField(name)));
    }

    /**
     * Returns accessible method.
     * Same as {@link Class#getDeclaredMethod(String, Class[])}.
     *
     * @param type {@link Class} instance
     * @param name method name
     * @param parameterTypes parameter types
     * @return method
     */
    public static Method getMethod(Class type, String name, Class... parameterTypes) {
        return replaceException(() -> makeAccessible(type.getDeclaredMethod(name, parameterTypes)));
    }

    /**
     * Returns accessible constructor.
     * Same as {@link Class#getDeclaredConstructor(Class[])}.
     *
     * @param type {@link Class} instance
     * @param parameterTypes parameter types
     * @param  type
     * @return method
     */
    public static  Constructor getConstructor(Class type, Class... parameterTypes) {
        return replaceException(() -> makeAccessible(type.getDeclaredConstructor(parameterTypes)));
    }

    /**
     * Makes object accessible.
     *
     * @param  can be field or method or constructor
     * @param object field or method or constructor
     * @return same object
     */
    public static  T makeAccessible(T object) {
        try {
            object.setAccessible(true);
        }
        catch (Exception e) {
            throw new ClonerException(
                "Error making a member accessible. " +
                    "On JDK 9..16 you can use --illegal-access=permit java parameter. " +
                    "On JDK 17+ you need to configure modules opens.",
                e);
        }
        return object;
    }

    /**
     * Returns {@code true} if the member of class is non-static.
     *
     * @param member field or method or constructor
     * @return {@code true} if the member is non-static
     */
    public static boolean isNonStatic(Member member) {
        return !Modifier.isStatic(member.getModifiers());
    }

    /**
     * Creates new instance of type using no-arg constructor.
     *
     * @param  type
     * @param type object type
     * @return new instance
     */
    public static  T newInstance(Class type) {
        Constructor constructor = getConstructor(type);
        return replaceException(constructor::newInstance);
    }

    /**
     * Creates new instance of type using no-arg constructor.
     *
     * @param  type
     * @param className class name
     * @return new instance
     */
    public static  T newInstance(String className) {
        return newInstance(classForName(className));
    }

    /**
     * Utility class.
     */
    private ReflectionUtils() {
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy