/*
 * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.beans;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.sun.beans.finder.ClassFinder;
import com.sun.beans.finder.ConstructorFinder;
import com.sun.beans.finder.MethodFinder;
import sun.reflect.misc.MethodUtil;

/**
 * A {@code Statement} object represents a primitive statement
 * in which a single method is applied to a target and
 * a set of arguments - as in {@code "a.setFoo(b)"}.
 * Note that where this example uses names
 * to denote the target and its argument, a statement
 * object does not require a name space and is constructed with
 * the values themselves.
 * The statement object associates the named method
 * with its environment as a simple set of values:
 * the target and an array of argument values.
 *
 * @since 1.4
 *
 * @author Philip Milne
 */
public class Statement {

    private static Object[] emptyArray = new Object[]{};

    static ExceptionListener defaultExceptionListener = new ExceptionListener() {
        public void exceptionThrown(Exception e) {
            System.err.println(e);
            // e.printStackTrace();
            System.err.println("Continuing ...");
        }
    };

    private final Object target;
    private final String methodName;
    private final Object[] arguments;
    ClassLoader loader;

    /**
     * Creates a new {@link Statement} object
     * for the specified target object to invoke the method
     * specified by the name and by the array of arguments.
     * <p>
     * The {@code target} and the {@code methodName} values should not be {@code null}.
     * Otherwise an attempt to execute this {@code Expression}
     * will result in a {@code NullPointerException}.
     * If the {@code arguments} value is {@code null},
     * an empty array is used as the value of the {@code arguments} property.
     *
     * @param target  the target object of this statement
     * @param methodName  the name of the method to invoke on the specified target
     * @param arguments  the array of arguments to invoke the specified method
     */
    @ConstructorProperties({"target", "methodName", "arguments"})
    public Statement(Object target, String methodName, Object[] arguments) {
        this.target = target;
        this.methodName = methodName;
        this.arguments = (arguments == null) ? emptyArray : arguments.clone();
    }

    /**
     * Returns the target object of this statement.
     * If this method returns {@code null},
     * the {@link #execute} method
     * throws a {@code NullPointerException}.
     *
     * @return the target object of this statement
     */
    public Object getTarget() {
        return target;
    }

    /**
     * Returns the name of the method to invoke.
     * If this method returns {@code null},
     * the {@link #execute} method
     * throws a {@code NullPointerException}.
     *
     * @return the name of the method
     */
    public String getMethodName() {
        return methodName;
    }

    /**
     * Returns the arguments for the method to invoke.
     * The number of arguments and their types
     * must match the method being  called.
     * {@code null} can be used as a synonym of an empty array.
     *
     * @return the array of arguments
     */
    public Object[] getArguments() {
        return this.arguments.clone();
    }

    /**
     * The {@code execute} method finds a method whose name is the same
     * as the {@code methodName} property, and invokes the method on
     * the target.
     *
     * When the target's class defines many methods with the given name
     * the implementation should choose the most specific method using
     * the algorithm specified in the Java Language Specification
     * (15.11). The dynamic class of the target and arguments are used
     * in place of the compile-time type information and, like the
     * {@link java.lang.reflect.Method} class itself, conversion between
     * primitive values and their associated wrapper classes is handled
     * internally.
     * <p>
     * The following method types are handled as special cases:
     * <ul>
     * <li>
     * Static methods may be called by using a class object as the target.
     * <li>
     * The reserved method name "new" may be used to call a class's constructor
     * as if all classes defined static "new" methods. Constructor invocations
     * are typically considered {@code Expression}s rather than {@code Statement}s
     * as they return a value.
     * <li>
     * The method names "get" and "set" defined in the {@link java.util.List}
     * interface may also be applied to array instances, mapping to
     * the static methods of the same name in the {@code Array} class.
     * </ul>
     *
     * @throws NullPointerException if the value of the {@code target} or
     *                              {@code methodName} property is {@code null}
     * @throws NoSuchMethodException if a matching method is not found
     * @throws Exception that is thrown by the invoked method
     *
     * @see java.lang.reflect.Method
     */
    public void execute() throws Exception {
        invoke();
    }

    Object invoke() throws Exception {
        Object target = getTarget();
        String methodName = getMethodName();

        if (target == null || methodName == null) {
            throw new NullPointerException((target == null ? "target" :
                                            "methodName") + " should not be null");
        }

        Object[] arguments = getArguments();
        if (arguments == null) {
            arguments = emptyArray;
        } else {
            arguments = arguments.clone();
        }
        if (target == Class.class && methodName.equals("forName")) {
            final String name = (String) arguments[0];
            if (arguments.length == 1) {
                // Class.forName(String className) won't load classes outside
                // of core from a class inside core. Special
                // case this method.
                return ClassFinder.resolveClass(name, this.loader);
            }
        }
        Class<?>[] argClasses = new Class<?>[arguments.length];
        for(int i = 0; i < arguments.length; i++) {
            argClasses[i] = (arguments[i] == null) ? null : arguments[i].getClass();
        }

        AccessibleObject m = null;
        if (target instanceof Class) {
            /*
            For class methods, simulate the effect of a meta class
            by taking the union of the static methods of the
            actual class, with the instance methods of "Class.class"
            and the overloaded "newInstance" methods defined by the
            constructors.
            This way "System.class", for example, will perform both
            the static method getProperties() and the instance method
            getSuperclass() defined in "Class.class".
            */
            if (methodName.equals("new")) {
                methodName = "newInstance";
            }
            // Provide a short form for array instantiation by faking an nary-constructor.
            if (methodName.equals("newInstance") && ((Class)target).isArray()) {
                Object result = Array.newInstance(((Class)target).getComponentType(), arguments.length);
                for(int i = 0; i < arguments.length; i++) {
                    Array.set(result, i, arguments[i]);
                }
                return result;
            }
            if (methodName.equals("newInstance") && arguments.length != 0) {
                // The Character class, as of 1.4, does not have a constructor
                // which takes a String. All of the other "wrapper" classes
                // for Java's primitive types have a String constructor so we
                // fake such a constructor here so that this special case can be
                // ignored elsewhere.
                if (target == Character.class && arguments.length == 1 &&
                    argClasses[0] == String.class) {
                    return ((String)arguments[0]).charAt(0);
                }
                try {
                    m = ConstructorFinder.findConstructor((Class)target, argClasses);
                }
                catch (NoSuchMethodException exception) {
                    m = null;
                }
            }
            if (m == null && target != Class.class) {
                m = getMethod((Class)target, methodName, argClasses);
            }
            if (m == null) {
                m = getMethod(Class.class, methodName, argClasses);
            }
        }
        else {
            /*
            This special casing of arrays is not necessary, but makes files
            involving arrays much shorter and simplifies the archiving infrastructure.
            The Array.set() method introduces an unusual idea - that of a static method
            changing the state of an instance. Normally statements with side
            effects on objects are instance methods of the objects themselves
            and we reinstate this rule (perhaps temporarily) by special-casing arrays.
            */
            if (target.getClass().isArray() &&
                (methodName.equals("set") || methodName.equals("get"))) {
                int index = ((Integer)arguments[0]).intValue();
                if (methodName.equals("get")) {
                    return Array.get(target, index);
                }
                else {
                    Array.set(target, index, arguments[1]);
                    return null;
                }
            }
            m = getMethod(target.getClass(), methodName, argClasses);
        }
        if (m != null) {
            try {
                if (m instanceof Method) {
                    return MethodUtil.invoke((Method)m, target, arguments);
                }
                else {
                    return ((Constructor)m).newInstance(arguments);
                }
            }
            catch (IllegalAccessException iae) {
                throw new Exception("Statement cannot invoke: " +
                                    methodName + " on " + target.getClass(),
                                    iae);
            }
            catch (InvocationTargetException ite) {
                Throwable te = ite.getCause();
                if (te instanceof Exception) {
                    throw (Exception)te;
                }
                else {
                    throw ite;
                }
            }
        }
        throw new NoSuchMethodException(toString());
    }

    String instanceName(Object instance) {
        if (instance == null) {
            return "null";
        } else if (instance.getClass() == String.class) {
            return "\""+(String)instance + "\"";
        } else {
            // Note: there is a minor problem with using the non-caching
            // NameGenerator method. The return value will not have
            // specific information about the inner class name. For example,
            // In 1.4.2 an inner class would be represented as JList$1 now
            // would be named Class.

            return NameGenerator.unqualifiedClassName(instance.getClass());
        }
    }

    /**
     * Prints the value of this statement using a Java-style syntax.
     */
    public String toString() {
        // Respect a subclass's implementation here.
        Object target = getTarget();
        String methodName = getMethodName();
        Object[] arguments = getArguments();
        if (arguments == null) {
            arguments = emptyArray;
        }
        StringBuilder result = new StringBuilder(instanceName(target) + "." + methodName + "(");
        int n = arguments.length;
        for(int i = 0; i < n; i++) {
            result.append(instanceName(arguments[i]));
            if (i != n -1) {
                result.append(", ");
            }
        }
        result.append(");");
        return result.toString();
    }

    static Method getMethod(Class<?> type, String name, Class<?>... args) {
        try {
            return MethodFinder.findMethod(type, name, args);
        }
        catch (NoSuchMethodException exception) {
            return null;
        }
    }
}
