/*
 * 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 flex.messaging.util;

import flex.messaging.MessageException;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.SerializationException;
import flex.messaging.validators.DeserializationValidator;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

/**
 * Utility class to create instances of Complex Types
 * and handle error conditions consistently across the RemoteObject
 * code base.
 */
public class ClassUtil {
    private static final int TYPE_NOT_FOUND = 10008;
    private static final int UNEXPECTED_TYPE = 10009;
    private static final int CANNOT_CREATE_TYPE = 10010;
    private static final int SECURITY_ERROR = 10011;
    private static final int UNKNOWN_ERROR = 10012;

    private static final String NULL = "null";

    private ClassUtil() {
    }

    /**
     * Create a class of the specified type.
     * Use {@link #createClass(String, ClassLoader)} and explicitly provide the MessageBroker class loader
     *
     * @param type fully qualified class name
     * @return the class instance
     */
    public static Class createClass(String type) {
        return createClass(type, null);
    }

    /**
     * Create a class of the specified type using the provided class loader.
     *
     * @param type   fully qualified class name
     * @param loader class loader, if null the class loader that loaded ClassUtil is used
     * @return the class instance
     */
    public static Class createClass(String type, ClassLoader loader) {
        try {
            if (type != null)
                type = type.trim();

            if (loader == null) // will use the loader for this class
                return Class.forName(type);
            return Class.forName(type, true, loader);
        } catch (ClassNotFoundException cnf) {
            // Cannot invoke type '{type}'
            MessageException ex = new MessageException();
            ex.setMessage(TYPE_NOT_FOUND, new Object[]{type});
            ex.setDetails(TYPE_NOT_FOUND, "0", new Object[]{type});
            ex.setCode(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE);
            throw ex;
        }
    }

    /**
     * Creates the default instance of the class and verifies that it matches
     * with the expected class type, if one passed in.
     *
     * @param cls              The class to create.
     * @param expectedInstance The expected class type.
     * @return The default instance of the class.
     */
    public static Object createDefaultInstance(Class cls, Class expectedInstance) {
        return ClassUtil.createDefaultInstance(cls, expectedInstance, false /*validate*/);
    }

    /**
     * Creates the default instance of the class and verifies that it matches
     * with the expected class type, if one passed in. It also validates the creation
     * of the instance with the deserialization validator, if one exists.
     *
     * @param cls              The class to create.
     * @param expectedInstance The expected class type.
     * @param validate         Controls whether the creation of the instance is validated
     *                         with the deserialization validator.
     * @return The default instance of the class.
     */
    public static Object createDefaultInstance(Class cls, Class expectedInstance, boolean validate) {
        if (validate)
            validateCreation(cls);

        String type = cls.getName();
        try {
            Object instance = cls.newInstance();

            if (expectedInstance != null && !expectedInstance.isInstance(instance)) {
                // Given type '{name}' is not of expected type '{expectedName}'.
                MessageException ex = new MessageException();
                ex.setMessage(UNEXPECTED_TYPE, new Object[]{instance.getClass().getName(), expectedInstance.getName()});
                ex.setCode(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE);
                throw ex;
            }

            return instance;
        } catch (IllegalAccessException ia) {
            boolean details = false;
            StringBuffer message = new StringBuffer("Unable to create a new instance of type ");
            message.append(type);

            //Look for a possible cause...

            // Class might not have a suitable constructor?
            if (!hasValidDefaultConstructor(cls)) {
                details = true;
            }

            // Unable to create a new instance of type '{type}'.
            MessageException ex = new MessageException();
            ex.setMessage(CANNOT_CREATE_TYPE, new Object[]{type});
            if (details) {
                //Types must have a public, no arguments constructor
                ex.setDetails(CANNOT_CREATE_TYPE, "0");
            }
            ex.setCode(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE);
            throw ex;
        } catch (InstantiationException ine) {
            String variant = null;

            //Look for a possible cause...

            if (cls.isInterface()) // Class is really an interface?
                variant = "1"; // Interfaces cannot be instantiated
            else if (isAbstract(cls))
                variant = "2"; //Abstract types cannot be instantiated.
            else if (!hasValidDefaultConstructor(cls)) // Class might not have a suitable constructor?
                variant = "3"; // Types cannot be instantiated without a public, no arguments constructor.

            MessageException ex = new MessageException();
            ex.setMessage(CANNOT_CREATE_TYPE, new Object[]{type});
            if (variant != null)
                ex.setDetails(CANNOT_CREATE_TYPE, variant);
            ex.setCode(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE);
            throw ex;
        } catch (SecurityException se) {
            MessageException ex = new MessageException();
            ex.setMessage(SECURITY_ERROR, new Object[]{type});
            ex.setCode(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE);
            ex.setRootCause(se);
            throw ex;
        } catch (MessageException me) {
            throw me;
        } catch (Exception e) {
            MessageException ex = new MessageException();
            ex.setMessage(UNKNOWN_ERROR, new Object[]{type});
            ex.setCode(MessageException.CODE_SERVER_RESOURCE_UNAVAILABLE);
            ex.setRootCause(e);
            throw ex;
        }
    }

    public static boolean isAbstract(Class cls) {
        try {
            if (cls != null) {
                int mod = cls.getModifiers();
                return Modifier.isAbstract(mod);
            }
        } catch (Throwable t) {
            return false;
        }

        return false;
    }

    public static boolean hasValidDefaultConstructor(Class cls) {
        try {
            if (cls != null) {
                Constructor c = cls.getConstructor();
                int mod = c.getModifiers();
                return Modifier.isPublic(mod);
            }
        } catch (Throwable t) {
            return false;
        }

        return false;
    }

    public static String classLoaderToString(ClassLoader cl) {
        if (cl == null)
            return NULL;

        if (cl == ClassLoader.getSystemClassLoader())
            return "system";

        StringBuffer sb = new StringBuffer();
        sb.append("hashCode: " + System.identityHashCode(cl) + " (parent " + ClassUtil.classLoaderToString(cl.getParent()) + ")");
        return sb.toString();
    }

    /**
     * Validates the assignment of a value to an index of an Array or List instance
     * against the deserialization validator. If the assignment is not valid,
     * SerializationException is thrown.
     *
     * @param obj   The Array or List instance.
     * @param index The index at which the value is being assigned.
     * @param value The value that is assigned to the index.
     */
    public static void validateAssignment(Object obj, int index, Object value) {
        SerializationContext context = SerializationContext.getSerializationContext();
        DeserializationValidator validator = context.getDeserializationValidator();
        if (validator == null)
            return;

        boolean valid = true;
        try {
            valid = validator.validateAssignment(obj, index, value);
        } catch (Exception e) {
            // Assignment validation of the object with type '{0}' for the index '{1}' failed.
            SerializationException se = new SerializationException();
            se.setMessage(10313, new Object[]{obj == null ? NULL : obj.getClass().getName(), index});
            se.setRootCause(e);
            throw se;
        }
        if (!valid) {
            SerializationException se = new SerializationException();
            se.setMessage(10313, new Object[]{obj == null ? NULL : obj.getClass().getName(), index});
            throw se;
        }
    }

    /**
     * Validates the assignment of a property of an instance of a class to a value
     * against the deserialization validator. If the assignment is not valid,
     * SerializationException is thrown.
     *
     * @param obj      The class instance whose property is being assigned to a value.
     * @param propName The name of the property that is being assigned.
     * @param value    The value that the property is being assigned to.
     */
    public static void validateAssignment(Object obj, String propName, Object value) {
        SerializationContext context = SerializationContext.getSerializationContext();
        DeserializationValidator validator = context.getDeserializationValidator();
        if (validator == null)
            return;

        boolean valid = true;
        try {
            valid = validator.validateAssignment(obj, propName, value);
        } catch (Exception e) {
            // Assignment validation of the object with type '{0}' for the property '{1}' failed.
            SerializationException se = new SerializationException();
            se.setMessage(10312, new Object[]{obj == null ? NULL : obj.getClass().getName(), propName});
            se.setRootCause(e);
            throw se;
        }
        if (!valid) {
            SerializationException se = new SerializationException();
            se.setMessage(10312, new Object[]{obj == null ? NULL : obj.getClass().getName(), propName});
            throw se;
        }
    }

    /**
     * Validates the creation of the class instance against the deserialization
     * validator, if one exists. If the class creation is not valid,
     * SerializationException is thrown.
     *
     * @param cls The class to validate.
     */
    public static void validateCreation(Class<?> cls) {
        SerializationContext context = SerializationContext.getSerializationContext();
        DeserializationValidator validator = context.getDeserializationValidator();
        if (validator == null)
            return;

        boolean valid = true;
        try {
            valid = validator.validateCreation(cls);
        } catch (Exception e) {
            // Creation validation for class '{0}' failed.
            SerializationException se = new SerializationException();
            se.setMessage(10311, new Object[]{cls == null ? NULL : cls.getName()});
            se.setRootCause(e);
            throw se;
        }
        if (!valid) {
            // Creation validation for class '{0}' failed.
            SerializationException se = new SerializationException();
            se.setMessage(10311, new Object[]{cls == null ? NULL : cls.getName()});
            throw se;
        }
    }
}
