/*
 * 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.
 */

package org.apache.commons.configuration2;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Iterator;

import org.apache.commons.configuration2.event.ConfigurationErrorEvent;
import org.apache.commons.configuration2.event.Event;
import org.apache.commons.configuration2.event.EventListener;
import org.apache.commons.configuration2.event.EventSource;
import org.apache.commons.configuration2.event.EventType;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.configuration2.sync.NoOpSynchronizer;
import org.apache.commons.configuration2.sync.Synchronizer;
import org.apache.commons.configuration2.tree.ExpressionEngine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Miscellaneous utility methods for configurations.
 *
 * @see ConfigurationConverter Utility methods to convert configurations.
 *
 */
public final class ConfigurationUtils
{
    /** Constant for the name of the clone() method.*/
    private static final String METHOD_CLONE = "clone";

    /**
     * An array with interfaces to be implemented by a proxy for an immutable
     * configuration.
     */
    private static final Class<?>[] IMMUTABLE_CONFIG_IFCS = {
        ImmutableConfiguration.class
    };

    /**
     * An array with interfaces to be implemented by a proxy for an immutable
     * hierarchical configuration.
     */
    private static final Class<?>[] IMMUTABLE_HIERARCHICAL_CONFIG_IFCS = {
        ImmutableHierarchicalConfiguration.class
    };
    /**
     * A dummy event source that is returned by {@code asEventSource()} if a
     * mock object has to be returned. It provides empty dummy implementations
     * for all interface methods.
     */
    private static final EventSource DUMMY_EVENT_SOURCE = new EventSource()
    {

        @Override
        public <T extends Event> void addEventListener(final EventType<T> eventType,
                final EventListener<? super T> listener)
        {
        }

        @Override
        public <T extends Event> boolean removeEventListener(
                final EventType<T> eventType, final EventListener<? super T> listener)
        {
            return false;
        }
    };

    /** The logger.*/
    private static final Log LOG = LogFactory.getLog(ConfigurationUtils.class);

    /**
     * Private constructor. Prevents instances from being created.
     */
    private ConfigurationUtils()
    {
        // to prevent instantiation...
    }

    /**
     * Dump the configuration key/value mappings to some ouput stream.
     *
     * @param configuration the configuration
     * @param out the output stream to dump the configuration to
     * @since 2.2
     */
    public static void dump(final ImmutableConfiguration configuration, final PrintStream out)
    {
        dump(configuration, new PrintWriter(out));
    }

    /**
     * Dump the configuration key/value mappings to some ouput stream.
     * This version of the method exists only for backwards compatibility reason.
     *
     * @param configuration the configuration
     * @param out the output stream to dump the configuration to
     */
    public static void dump(final Configuration configuration, final PrintStream out)
    {
        dump((ImmutableConfiguration) configuration, out);
    }

    /**
     * Dump the configuration key/value mappings to some writer.
     *
     * @param configuration the configuration
     * @param out the writer to dump the configuration to
     * @since 2.2
     */
    public static void dump(final ImmutableConfiguration configuration, final PrintWriter out)
    {
        for (final Iterator<String> keys = configuration.getKeys(); keys.hasNext();)
        {
            final String key = keys.next();
            final Object value = configuration.getProperty(key);
            out.print(key);
            out.print("=");
            out.print(value);

            if (keys.hasNext())
            {
                out.println();
            }
        }

        out.flush();
    }

    /**
     * Dump the configuration key/value mappings to some writer.
     * This version of the method exists only for backwards compatibility reason.
     *
     * @param configuration the configuration
     * @param out the writer to dump the configuration to
     */
    public static void dump(final Configuration configuration, final PrintWriter out)
    {
        dump((ImmutableConfiguration) configuration, out);
    }

    /**
     * Get a string representation of the key/value mappings of a
     * configuration.
     *
     * @param configuration the configuration
     * @return a string representation of the configuration
     * @since 2.2
     */
    public static String toString(final ImmutableConfiguration configuration)
    {
        final StringWriter writer = new StringWriter();
        dump(configuration, new PrintWriter(writer));
        return writer.toString();
    }

    /**
     * Get a string representation of the key/value mappings of a
     * configuration.
     * This version of the method exists only for backwards compatibility reason.
     *
     * @param configuration the configuration
     * @return a string representation of the configuration
     */
    public static String toString(final Configuration configuration)
    {
        return toString((ImmutableConfiguration) configuration);
    }

    /**
     * <p>Copy all properties from the source configuration to the target
     * configuration. Properties in the target configuration are replaced with
     * the properties with the same key in the source configuration.</p>
     * <p><em>Note:</em> This method is not able to handle some specifics of
     * configurations derived from {@code AbstractConfiguration} (e.g.
     * list delimiters). For a full support of all of these features the
     * {@code copy()} method of {@code AbstractConfiguration} should
     * be used. In a future release this method might become deprecated.</p>
     *
     * @param source the source configuration
     * @param target the target configuration
     * @since 2.2
     */
    public static void copy(final ImmutableConfiguration source, final Configuration target)
    {
        for (final Iterator<String> keys = source.getKeys(); keys.hasNext();)
        {
            final String key = keys.next();
            target.setProperty(key, source.getProperty(key));
        }
    }

    /**
     * <p>Copy all properties from the source configuration to the target
     * configuration. Properties in the target configuration are replaced with
     * the properties with the same key in the source configuration.</p>
     * <p><em>Note:</em> This method is not able to handle some specifics of
     * configurations derived from {@code AbstractConfiguration} (e.g.
     * list delimiters). For a full support of all of these features the
     * {@code copy()} method of {@code AbstractConfiguration} should
     * be used. In a future release this method might become deprecated.</p>
     *
     * @param source the source configuration
     * @param target the target configuration
     * @since 1.1
     */
    public static void copy(final Configuration source, final Configuration target)
    {
        copy((ImmutableConfiguration) source, target);
    }

    /**
     * <p>Append all properties from the source configuration to the target
     * configuration. Properties in the source configuration are appended to
     * the properties with the same key in the target configuration.</p>
     * <p><em>Note:</em> This method is not able to handle some specifics of
     * configurations derived from {@code AbstractConfiguration} (e.g.
     * list delimiters). For a full support of all of these features the
     * {@code copy()} method of {@code AbstractConfiguration} should
     * be used. In a future release this method might become deprecated.</p>
     *
     * @param source the source configuration
     * @param target the target configuration
     * @since 2.2
     */
    public static void append(final ImmutableConfiguration source, final Configuration target)
    {
        for (final Iterator<String> keys = source.getKeys(); keys.hasNext();)
        {
            final String key = keys.next();
            target.addProperty(key, source.getProperty(key));
        }
    }

    /**
     * <p>Append all properties from the source configuration to the target
     * configuration. Properties in the source configuration are appended to
     * the properties with the same key in the target configuration.</p>
     * <p><em>Note:</em> This method is not able to handle some specifics of
     * configurations derived from {@code AbstractConfiguration} (e.g.
     * list delimiters). For a full support of all of these features the
     * {@code copy()} method of {@code AbstractConfiguration} should
     * be used. In a future release this method might become deprecated.</p>
     *
     * @param source the source configuration
     * @param target the target configuration
     * @since 1.1
     */
    public static void append(final Configuration source, final Configuration target)
    {
        append((ImmutableConfiguration) source, target);
    }

    /**
     * Converts the passed in configuration to a hierarchical one. If the
     * configuration is already hierarchical, it is directly returned. Otherwise
     * all properties are copied into a new hierarchical configuration.
     *
     * @param conf the configuration to convert
     * @return the new hierarchical configuration (the result is <b>null</b> if
     * and only if the passed in configuration is <b>null</b>)
     * @since 1.3
     */
    public static HierarchicalConfiguration<?> convertToHierarchical(
            final Configuration conf)
    {
        return convertToHierarchical(conf, null);
    }

    /**
     * Converts the passed in {@code Configuration} object to a
     * hierarchical one using the specified {@code ExpressionEngine}. This
     * conversion works by adding the keys found in the configuration to a newly
     * created hierarchical configuration. When adding new keys to a
     * hierarchical configuration the keys are interpreted by its
     * {@code ExpressionEngine}. If they contain special characters (e.g.
     * brackets) that are treated in a special way by the default expression
     * engine, it may be necessary using a specific engine that can deal with
     * such characters. Otherwise <b>null</b> can be passed in for the
     * {@code ExpressionEngine}; then the default expression engine is
     * used. If the passed in configuration is already hierarchical, it is
     * directly returned. (However, the {@code ExpressionEngine} is set if
     * it is not <b>null</b>.) Otherwise all properties are copied into a new
     * hierarchical configuration.
     *
     * @param conf the configuration to convert
     * @param engine the {@code ExpressionEngine} for the hierarchical
     *        configuration or <b>null</b> for the default
     * @return the new hierarchical configuration (the result is <b>null</b> if
     *         and only if the passed in configuration is <b>null</b>)
     * @since 1.6
     */
    public static HierarchicalConfiguration<?> convertToHierarchical(
            final Configuration conf, final ExpressionEngine engine)
    {
        if (conf == null)
        {
            return null;
        }

        if (conf instanceof HierarchicalConfiguration)
        {
            final HierarchicalConfiguration<?> hc = (HierarchicalConfiguration<?>) conf;
            if (engine != null)
            {
                hc.setExpressionEngine(engine);
            }

            return hc;
        }
        final BaseHierarchicalConfiguration hc = new BaseHierarchicalConfiguration();
        if (engine != null)
        {
            hc.setExpressionEngine(engine);
        }

        // Per default, a DisabledListDelimiterHandler is set.
        // So list delimiters in property values are not an issue.
        hc.copy(conf);
        return hc;
    }

    /**
     * Clones the given configuration object if this is possible. If the passed
     * in configuration object implements the {@code Cloneable}
     * interface, its {@code clone()} method will be invoked. Otherwise
     * an exception will be thrown.
     *
     * @param config the configuration object to be cloned (can be <b>null</b>)
     * @return the cloned configuration (<b>null</b> if the argument was
     * <b>null</b>, too)
     * @throws ConfigurationRuntimeException if cloning is not supported for
     * this object
     * @since 1.3
     */
    public static Configuration cloneConfiguration(final Configuration config)
            throws ConfigurationRuntimeException
    {
        if (config == null)
        {
            return null;
        }
        try
        {
            return (Configuration) clone(config);
        }
        catch (final CloneNotSupportedException cnex)
        {
            throw new ConfigurationRuntimeException(cnex);
        }
    }

    /**
     * Returns a clone of the passed in object if cloning is supported or the
     * object itself if not. This method checks whether the passed in object
     * implements the {@code Cloneable} interface. If this is the case, the
     * {@code clone()} method is invoked. Otherwise, the object is directly
     * returned. Errors that might occur during reflection calls are caught and
     * also cause this method to return the original object.
     *
     * @param obj the object to be cloned
     * @return the result of the cloning attempt
     * @since 2.0
     */
    public static Object cloneIfPossible(final Object obj)
    {
        try
        {
            return clone(obj);
        }
        catch (final Exception ex)
        {
            return obj;
        }
    }

    /**
     * An internally used helper method for cloning objects. This implementation
     * is not very sophisticated nor efficient. Maybe it can be replaced by an
     * implementation from Commons Lang later. The method checks whether the
     * passed in object implements the {@code Cloneable} interface. If
     * this is the case, the {@code clone()} method is invoked by
     * reflection. Errors that occur during the cloning process are re-thrown as
     * runtime exceptions.
     *
     * @param obj the object to be cloned
     * @return the cloned object
     * @throws CloneNotSupportedException if the object cannot be cloned
     */
    static Object clone(final Object obj) throws CloneNotSupportedException
    {
        if (obj instanceof Cloneable)
        {
            try
            {
                final Method m = obj.getClass().getMethod(METHOD_CLONE);
                return m.invoke(obj);
            }
            catch (final NoSuchMethodException nmex)
            {
                throw new CloneNotSupportedException(
                        "No clone() method found for class"
                                + obj.getClass().getName());
            }
            catch (final IllegalAccessException | InvocationTargetException itex)
            {
                throw new ConfigurationRuntimeException(itex);
            }
        }
        throw new CloneNotSupportedException(obj.getClass().getName()
                + " does not implement Cloneable");
    }

    /**
     * Creates a clone of the specified {@code Synchronizer}. This method can be
     * called by {@code clone()} implementations in configuration classes that
     * also need to copy the {@code Synchronizer} object. This method can handle
     * some well-known {@code Synchronizer} implementations directly. For other
     * classes, it uses the following algorithm:
     * <ul>
     * <li>If the class of the {@code Synchronizer} has a standard constructor,
     * a new instance is created using reflection.</li>
     * <li>If this is not possible, it is tried whether the object can be
     * cloned.</li>
     * </ul>
     * If all attempts fail, a {@code ConfigurationRuntimeException} is thrown.
     *
     * @param sync the {@code Synchronizer} object to be cloned
     * @return the clone of this {@code Synchronizer}
     * @throws ConfigurationRuntimeException if no clone can be created
     * @throws IllegalArgumentException if <b>null</b> is passed in
     */
    public static Synchronizer cloneSynchronizer(final Synchronizer sync)
    {
        if (sync == null)
        {
            throw new IllegalArgumentException("Synchronizer must not be null!");
        }
        if (NoOpSynchronizer.INSTANCE == sync)
        {
            return sync;
        }

        try
        {
            return sync.getClass().newInstance();
        }
        catch (final Exception ex)
        {
            LOG.info("Cannot create new instance of " + sync.getClass());
        }

        try
        {
            return (Synchronizer) clone(sync);
        }
        catch (final CloneNotSupportedException cnex)
        {
            throw new ConfigurationRuntimeException(
                    "Cannot clone Synchronizer " + sync);
        }
    }

    /**
     * Enables runtime exceptions for the specified configuration object. This
     * method can be used for configuration implementations that may face errors
     * on normal property access, e.g. {@code DatabaseConfiguration} or
     * {@code JNDIConfiguration}. Per default such errors are simply
     * logged and then ignored. This implementation will register a special
     * {@link EventListener} that throws a runtime
     * exception (namely a {@code ConfigurationRuntimeException}) on
     * each received error event.
     *
     * @param src the configuration, for which runtime exceptions are to be
     * enabled; this configuration must implement {@link EventSource}
     */
    public static void enableRuntimeExceptions(final Configuration src)
    {
        if (!(src instanceof EventSource))
        {
            throw new IllegalArgumentException(
                    "Configuration must implement EventSource!");
        }
        ((EventSource) src).addEventListener(ConfigurationErrorEvent.ANY,
                event -> {
                    // Throw a runtime exception
                    throw new ConfigurationRuntimeException(event
                            .getCause());
                });
    }

    /**
     * Loads the class with the given name. This method is used whenever a class
     * has to be loaded dynamically. It first tries the current thread's context
     * class loader. If this fails, the class loader of this class is tried.
     *
     * @param clsName the name of the class to be loaded
     * @return the loaded class
     * @throws ClassNotFoundException if the class cannot be resolved
     * @since 2.0
     */
    public static Class<?> loadClass(final String clsName)
            throws ClassNotFoundException
    {
        if (LOG.isDebugEnabled())
        {
            LOG.debug("Loading class " + clsName);
        }

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        try
        {
            if (cl != null)
            {
                return cl.loadClass(clsName);
            }
        }
        catch (final ClassNotFoundException cnfex)
        {
            LOG.info("Could not load class " + clsName
                    + " using CCL. Falling back to default CL.", cnfex);
        }

        return ConfigurationUtils.class.getClassLoader().loadClass(clsName);
    }

    /**
     * Loads the class with the specified name re-throwing
     * {@code ClassNotFoundException} exceptions as runtime exceptions. This
     * method works like {@link #loadClass(String)}. However, checked exceptions
     * are caught and re-thrown as {@code ConfigurationRuntimeException}.
     *
     * @param clsName the name of the class to be loaded
     * @return the loaded class
     * @throws ConfigurationRuntimeException if the class cannot be resolved
     * @since 2.0
     */
    public static Class<?> loadClassNoEx(final String clsName)
    {
        try
        {
            return loadClass(clsName);
        }
        catch (final ClassNotFoundException cnfex)
        {
            throw new ConfigurationRuntimeException("Cannot load class "
                    + clsName, cnfex);
        }
    }

    /**
     * Creates an {@code ImmutableConfiguration} from the given
     * {@code Configuration} object. This method creates a proxy object wrapping
     * the original configuration and making it available under the
     * {@code ImmutableConfiguration} interface. Through this interface the
     * configuration cannot be manipulated. It is also not possible to cast the
     * returned object back to a {@code Configuration} instance to circumvent
     * this protection.
     *
     * @param c the {@code Configuration} to be wrapped (must not be
     *        <b>null</b>)
     * @return an {@code ImmutableConfiguration} view on the specified
     *         {@code Configuration} object
     * @throws NullPointerException if the passed in {@code Configuration} is
     *         <b>null</b>
     * @since 2.0
     */
    public static ImmutableConfiguration unmodifiableConfiguration(
            final Configuration c)
    {
        return createUnmodifiableConfiguration(IMMUTABLE_CONFIG_IFCS, c);
    }

    /**
     * Creates an {@code ImmutableHierarchicalConfiguration} from the given
     * {@code HierarchicalConfiguration} object. This method works exactly like
     * the method with the same name, but it operates on hierarchical
     * configurations.
     *
     * @param c the {@code HierarchicalConfiguration} to be wrapped (must not be
     *        <b>null</b>)
     * @return an {@code ImmutableHierarchicalConfiguration} view on the
     *         specified {@code HierarchicalConfiguration} object
     * @throws NullPointerException if the passed in
     *         {@code HierarchicalConfiguration} is <b>null</b>
     * @since 2.0
     */
    public static ImmutableHierarchicalConfiguration unmodifiableConfiguration(
            final HierarchicalConfiguration<?> c)
    {
        return (ImmutableHierarchicalConfiguration) createUnmodifiableConfiguration(
                IMMUTABLE_HIERARCHICAL_CONFIG_IFCS, c);
    }

    /**
     * Helper method for creating a proxy for an unmodifiable configuration. The
     * interfaces the proxy should implement are passed as argument.
     *
     * @param ifcs an array with the interface classes the proxy must implement
     * @param c the configuration object to be wrapped
     * @return a proxy object for an immutable configuration
     * @throws NullPointerException if the configuration is <b>null</b>
     */
    private static ImmutableConfiguration createUnmodifiableConfiguration(
            final Class<?>[] ifcs, final Configuration c)
    {
        return (ImmutableConfiguration) Proxy.newProxyInstance(
                ConfigurationUtils.class.getClassLoader(), ifcs,
                new ImmutableConfigurationInvocationHandler(c));
    }

    /**
     * Casts the specified object to an {@code EventSource} if possible. The
     * boolean argument determines the method's behavior if the object does not
     * implement the {@code EventSource} event: if set to <b>false</b>, a
     * {@code ConfigurationRuntimeException} is thrown; if set to <b>true</b>, a
     * dummy {@code EventSource} is returned; on this object all methods can be
     * called, but they do not have any effect.
     *
     * @param obj the object to be cast as {@code EventSource}
     * @param mockIfUnsupported a flag whether a mock object should be returned
     *        if necessary
     * @return an {@code EventSource}
     * @throws ConfigurationRuntimeException if the object cannot be cast to
     *         {@code EventSource} and the mock flag is <b>false</b>
     * @since 2.0
     */
    public static EventSource asEventSource(final Object obj,
            final boolean mockIfUnsupported)
    {
        if (obj instanceof EventSource)
        {
            return (EventSource) obj;
        }

        if (!mockIfUnsupported)
        {
            throw new ConfigurationRuntimeException(
                    "Cannot cast to EventSource: " + obj);
        }
        return DUMMY_EVENT_SOURCE;
    }
}
