/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

// Contributors:  Georg Lundesgaard

package org.apache.log4j.config;

import org.apache.log4j.Appender;
import org.apache.log4j.Level;
import org.apache.log4j.Priority;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.OptionHandler;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.util.OptionConverter;
import org.apache.logging.log4j.status.StatusLogger;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InterruptedIOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * General purpose Object property setter. Clients repeatedly invokes
 * {@link #setProperty setProperty(name,value)} in order to invoke setters
 * on the Object specified in the constructor. This class relies on the
 * JavaBeans {@link Introspector} to analyze the given Object Class using
 * reflection.
 *
 * <p>Usage:
 * <pre>
 * PropertySetter ps = new PropertySetter(anObject);
 * ps.set("name", "Joe");
 * ps.set("age", "32");
 * ps.set("isMale", "true");
 * </pre>
 * will cause the invocations anObject.setName("Joe"), anObject.setAge(32),
 * and setMale(true) if such methods exist with those signatures.
 * Otherwise an {@link IntrospectionException} are thrown.
 */
public class PropertySetter {
    private static final Logger LOGGER = StatusLogger.getLogger();
    protected Object obj;
    protected PropertyDescriptor[] props;

    /**
     * Create a new PropertySetter for the specified Object. This is done
     * in prepartion for invoking {@link #setProperty} one or more times.
     *
     * @param obj the object for which to set properties
     */
    public PropertySetter(Object obj) {
        this.obj = obj;
    }

    /**
     * Set the properties of an object passed as a parameter in one
     * go. The <code>properties</code> are parsed relative to a
     * <code>prefix</code>.
     *
     * @param obj        The object to configure.
     * @param properties A java.util.Properties containing keys and values.
     * @param prefix     Only keys having the specified prefix will be set.
     */
    public static void setProperties(Object obj, Properties properties, String prefix) {
        new PropertySetter(obj).setProperties(properties, prefix);
    }

    /**
     * Uses JavaBeans {@link Introspector} to computer setters of object to be
     * configured.
     */
    protected void introspect() {
        try {
            BeanInfo bi = Introspector.getBeanInfo(obj.getClass());
            props = bi.getPropertyDescriptors();
        } catch (IntrospectionException ex) {
            LOGGER.error("Failed to introspect {}: {}", obj, ex.getMessage());
            props = new PropertyDescriptor[0];
        }
    }

    /**
     * Set the properites for the object that match the
     * <code>prefix</code> passed as parameter.
     * @param properties The properties.
     * @param prefix The prefix of the properties to use.
     */
    public void setProperties(Properties properties, String prefix) {
        int len = prefix.length();

        for (String key : properties.stringPropertyNames()) {

            // handle only properties that start with the desired prefix.
            if (key.startsWith(prefix)) {


                // ignore key if it contains dots after the prefix
                if (key.indexOf('.', len + 1) > 0) {
                    continue;
                }

                String value = OptionConverter.findAndSubst(key, properties);
                key = key.substring(len);
                if (("layout".equals(key) || "errorhandler".equals(key)) && obj instanceof Appender) {
                    continue;
                }
                //
                //   if the property type is an OptionHandler
                //     (for example, triggeringPolicy of org.apache.log4j.rolling.RollingFileAppender)
                PropertyDescriptor prop = getPropertyDescriptor(Introspector.decapitalize(key));
                if (prop != null
                        && OptionHandler.class.isAssignableFrom(prop.getPropertyType())
                        && prop.getWriteMethod() != null) {
                    OptionHandler opt = (OptionHandler)
                            OptionConverter.instantiateByKey(properties, prefix + key,
                                    prop.getPropertyType(),
                                    null);
                    PropertySetter setter = new PropertySetter(opt);
                    setter.setProperties(properties, prefix + key + ".");
                    try {
                        prop.getWriteMethod().invoke(this.obj, opt);
                    } catch (InvocationTargetException ex) {
                        if (ex.getTargetException() instanceof InterruptedException
                                || ex.getTargetException() instanceof InterruptedIOException) {
                            Thread.currentThread().interrupt();
                        }
                        LOGGER.warn("Failed to set property [{}] to value \"{}\".", key, value, ex);
                    } catch (IllegalAccessException | RuntimeException ex) {
                        LOGGER.warn("Failed to set property [{}] to value \"{}\".", key, value, ex);
                    }
                    continue;
                }

                setProperty(key, value);
            }
        }
        activate();
    }

    /**
     * Set a property on this PropertySetter's Object. If successful, this
     * method will invoke a setter method on the underlying Object. The
     * setter is the one for the specified property name and the value is
     * determined partly from the setter argument type and partly from the
     * value specified in the call to this method.
     *
     * <p>If the setter expects a String no conversion is necessary.
     * If it expects an int, then an attempt is made to convert 'value'
     * to an int using new Integer(value). If the setter expects a boolean,
     * the conversion is by new Boolean(value).
     *
     * @param name  name of the property
     * @param value String value of the property
     */
    public void setProperty(String name, String value) {
        if (value == null) {
            return;
        }

        name = Introspector.decapitalize(name);
        PropertyDescriptor prop = getPropertyDescriptor(name);

        //LOGGER.debug("---------Key: "+name+", type="+prop.getPropertyType());

        if (prop == null) {
            LOGGER.warn("No such property [" + name + "] in " +
                    obj.getClass().getName() + ".");
        } else {
            try {
                setProperty(prop, name, value);
            } catch (PropertySetterException ex) {
                LOGGER.warn("Failed to set property [{}] to value \"{}\".", name, value, ex.rootCause);
            }
        }
    }

    /**
     * Set the named property given a {@link PropertyDescriptor}.
     *
     * @param prop  A PropertyDescriptor describing the characteristics
     *              of the property to set.
     * @param name  The named of the property to set.
     * @param value The value of the property.
     * @throws PropertySetterException if no setter is available.
     */
    public void setProperty(PropertyDescriptor prop, String name, String value)
            throws PropertySetterException {
        Method setter = prop.getWriteMethod();
        if (setter == null) {
            throw new PropertySetterException("No setter for property [" + name + "].");
        }
        Class<?>[] paramTypes = setter.getParameterTypes();
        if (paramTypes.length != 1) {
            throw new PropertySetterException("#params for setter != 1");
        }

        Object arg;
        try {
            arg = convertArg(value, paramTypes[0]);
        } catch (Throwable t) {
            throw new PropertySetterException("Conversion to type [" + paramTypes[0] +
                    "] failed. Reason: " + t);
        }
        if (arg == null) {
            throw new PropertySetterException(
                    "Conversion to type [" + paramTypes[0] + "] failed.");
        }
        LOGGER.debug("Setting property [" + name + "] to [" + arg + "].");
        try {
            setter.invoke(obj, arg);
        } catch (InvocationTargetException ex) {
            if (ex.getTargetException() instanceof InterruptedException
                    || ex.getTargetException() instanceof InterruptedIOException) {
                Thread.currentThread().interrupt();
            }
            throw new PropertySetterException(ex);
        } catch (IllegalAccessException | RuntimeException ex) {
            throw new PropertySetterException(ex);
        }
    }


    /**
     * Convert <code>val</code> a String parameter to an object of a
     * given type.
     * @param val The value to convert.
     * @param type The type of the value to convert to.
     * @return The result of the conversion.
     */
    protected Object convertArg(String val, Class<?> type) {
        if (val == null) {
            return null;
        }

        String v = val.trim();
        if (String.class.isAssignableFrom(type)) {
            return val;
        } else if (Integer.TYPE.isAssignableFrom(type)) {
            return Integer.parseInt(v);
        } else if (Long.TYPE.isAssignableFrom(type)) {
            return Long.parseLong(v);
        } else if (Boolean.TYPE.isAssignableFrom(type)) {
            if ("true".equalsIgnoreCase(v)) {
                return Boolean.TRUE;
            } else if ("false".equalsIgnoreCase(v)) {
                return Boolean.FALSE;
            }
        } else if (Priority.class.isAssignableFrom(type)) {
            return org.apache.log4j.helpers.OptionConverter.toLevel(v, Level.DEBUG);
        } else if (ErrorHandler.class.isAssignableFrom(type)) {
            return OptionConverter.instantiateByClassName(v,
                    ErrorHandler.class, null);
        }
        return null;
    }


    protected PropertyDescriptor getPropertyDescriptor(String name) {
        if (props == null) {
            introspect();
        }
        for (PropertyDescriptor prop : props) {
            if (name.equals(prop.getName())) {
                return prop;
            }
        }
        return null;
    }

    public void activate() {
        if (obj instanceof OptionHandler) {
            ((OptionHandler) obj).activateOptions();
        }
    }
}
