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

import flex.messaging.config.ConfigMap;

import java.util.*;
import java.util.regex.Pattern;

/**
 * The <code>ClassDeserializationValidator</code> is provided as a default
 * implementation of <code>DeserializationValidator</code> and it simply
 * validates the creation of allowed and disallowed classes as specified in
 * the configuration.
 */
public class ClassDeserializationValidator implements DeserializationValidator {
    //--------------------------------------------------------------------------
    //
    // Public Static Constants
    //
    //--------------------------------------------------------------------------

    public static final String PROPERTY_ALLOW_CLASSES = "allow-classes";
    public static final String PROPERTY_DISALLOW_CLASSES = "disallow-classes";
    public static final String PROPERTY_CLASS_ATTR = "class";
    public static final String PROPERTY_NAME_ATTR = "name";

    private static final String[] DEFAULT_ALLOW_CLASSES = {
            "flex.messaging.io.amf.ASObject",
            "flex.messaging.io.amf.SerializedObject",
            "flex.messaging.io.ArrayCollection",
            "flex.messaging.io.ArrayList",
            "flex.messaging.messages.AcknowledgeMessage",
            "flex.messaging.messages.AcknowledgeMessageExt",
            "flex.messaging.messages.AsyncMessage",
            "flex.messaging.messages.AsyncMessageExt",
            "flex.messaging.messages.CommandMessage",
            "flex.messaging.messages.CommandMessageExt",
            "flex.messaging.messages.ErrorMessage",
            "flex.messaging.messages.HTTPMessage",
            "flex.messaging.messages.RemotingMessage",
            "flex.messaging.messages.SOAPMessage",
            "java.io.Externalizable",
            "java.lang.Boolean",
            "java.lang.Byte",
            "java.lang.Character",
            "java.lang.Double",
            "java.lang.Float",
            "java.lang.Integer",
            "java.lang.Long",
            "java.lang.Object",
            "java.lang.Short",
            "java.lang.String",
            "java.util.ArrayList",
            "java.util.Date",
            "java.util.HashMap",
            "org.w3c.dom.Document",
            "\\[B",
            "\\[Ljava.lang.Object;"
    };

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     * Instance level lock for thread-safe state changes.
     */
    protected final Object lock = new Object();

    /**
     * Used to keep track of encountered allow and disallow classes for faster lookup.
     */
    private Set<String> allowClasses;
    private Set<String> disallowClasses;

    /**
     * Used to keep track of allow and disallow class patterns.
     */
    private Map<String, Pattern> allowClassPatterns;
    private Map<String, Pattern> disallowClassPatterns;

    public ClassDeserializationValidator() {
        // Apply default allow classes
        for (String defaultAllowClassPattern : DEFAULT_ALLOW_CLASSES) {
            addAllowClassPattern(defaultAllowClassPattern);
        }
    }


    //--------------------------------------------------------------------------
    //
    // Public Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Adds a class pattern that should be allowed to be created.
     *
     * @param classNamePattern The name of the class which can be a regular expression.
     */
    public void addAllowClassPattern(String classNamePattern) {
        synchronized (lock) {
            if (allowClassPatterns == null) {
                allowClassPatterns = new HashMap<String, Pattern>();
            }

            allowClassPatterns.put(classNamePattern, Pattern.compile(classNamePattern));

            clearClassCache();
        }
    }

    /**
     * Removes a class pattern that should be allowed to be created..
     *
     * @param classNamePattern The name of the class which can be a regular expression.
     */
    public void removeAllowClassPattern(String classNamePattern) {
        synchronized (lock) {
            if (allowClassPatterns != null) {
                allowClassPatterns.remove(classNamePattern);
            }

            clearClassCache();
        }
    }

    /**
     * Adds a class pattern that should be disallowed to be created.
     *
     * @param classNamePattern The name of the class which can be a regular expression.
     */
    public void addDisallowClassPattern(String classNamePattern) {
        synchronized (lock) {
            if (disallowClassPatterns == null) {
                disallowClassPatterns = new HashMap<String, Pattern>();
            }

            disallowClassPatterns.put(classNamePattern, Pattern.compile(classNamePattern));

            clearClassCache();
        }
    }

    /**
     * Removes a class pattern that should be disallowed to be created..
     *
     * @param classNamePattern The name of the class which can be a regular expression.
     */
    public void removeDisallowClassPattern(String classNamePattern) {
        synchronized (lock) {
            if (disallowClassPatterns != null) {
                disallowClassPatterns.remove(classNamePattern);
            }

            clearClassCache();
        }
    }

    /**
     * This method is meant to validate the assignment of a value to an index of
     * an Array or List instance but this class only deals with class creations,
     * therefore this method always returns true.
     *
     * @param instance 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.
     * @return True.
     */
    public boolean validateAssignment(Object instance, int index, Object value) {
        return true;
    }

    /**
     * This method is meant to validate the assignment of a property of an instance
     * to a value but this class only deals with class creations, therefore this
     * method always returns true.
     *
     * @param instance     The instance with the property that is being assigned a new value.
     * @param propertyName The name of the property that is being assigned.
     * @param value        The value that the property is being assigned to.
     * @return True.
     */
    public boolean validateAssignment(Object instance, String propertyName, Object value) {
        return true;
    }

    /**
     * Validates the creation of a class as indicated by the allow and disallow
     * classes list. If the class is in both allow and disallow classes,
     * disallow classes list take precedence.
     *
     * @param c The class that is being created.
     * @return True if the creation is valid.
     */
    @Override
    public boolean validateCreation(Class<?> c) {
        String className = c == null ? null : c.getName();
        if (className == null) {
            return true;
        }

        // First, check against the encountered disallow-classes list.
        if (disallowClasses != null && disallowClasses.contains(className)) {
            return false;
        }

        // Then, check against the encountered allow-classes list.
        if (allowClasses != null && allowClasses.contains(className)) {
            return true;
        }

        // Otherwise, the class was encountered for the first time, need to
        // go through the disallow and allow class patterns list.

        // Disallow the class if there's a disallow-classes list, and the class is in that list.
        if (disallowClassPatterns != null && !disallowClassPatterns.isEmpty()) {
            for (Pattern pattern : disallowClassPatterns.values()) {
                if (pattern.matcher(className).matches()) {
                    addDisallowClass(className);
                    return false;
                }
            }
        }

        // Disallow the class if there's an allowed-classes list, and the class is NOT in that list.
        if (allowClassPatterns != null && !allowClassPatterns.isEmpty()) {
            for (Pattern pattern : allowClassPatterns.values()) {
                if (pattern.matcher(className).matches()) {
                    addAllowClass(className);
                    return true;
                }
            }
            // Disallow the class as it's not in allow-classes list.
            addDisallowClass(className);
            return false;
        }

        // Otherwise allow the class.
        addAllowClass(className);
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public void initialize(String id, ConfigMap properties) {
        if (properties == null || properties.size() == 0) {
            return;
        }

        // Process allow-classes.
        ConfigMap allowedClassesMap = properties.getPropertyAsMap(PROPERTY_ALLOW_CLASSES, null);
        if (allowedClassesMap != null && !allowedClassesMap.isEmpty()) {
            List<?> names = allowedClassesMap.getPropertyAsList(PROPERTY_CLASS_ATTR, null);
            if (names != null && !names.isEmpty()) {
                for (Object element : names) {
                    String name = ((ConfigMap) element).getProperty(PROPERTY_NAME_ATTR);
                    addAllowClassPattern(name);
                }
            }
        }

        // Process disallow-classes.
        ConfigMap disallowedClassesMap = properties.getPropertyAsMap(PROPERTY_DISALLOW_CLASSES, null);
        if (disallowedClassesMap != null && !disallowedClassesMap.isEmpty()) {
            List<?> names = disallowedClassesMap.getPropertyAsList(PROPERTY_CLASS_ATTR, null);
            if (names != null && !names.isEmpty()) {
                for (Object element : names) {
                    String name = ((ConfigMap) element).getProperty(PROPERTY_NAME_ATTR);
                    addDisallowClassPattern(name);
                }
            }
        }
    }

    //--------------------------------------------------------------------------
    //
    // Protected Methods
    //
    //--------------------------------------------------------------------------

    protected void addAllowClass(String className) {
        synchronized (lock) {
            if (allowClasses == null) {
                allowClasses = new HashSet<String>();
            }

            if (!allowClasses.contains(className)) {
                allowClasses.add(className);
            }
        }
    }

    protected void addDisallowClass(String className) {
        synchronized (lock) {
            if (disallowClasses == null) {
                disallowClasses = new HashSet<String>();
            }

            if (!disallowClasses.contains(className)) {
                disallowClasses.add(className);
            }
        }
    }

    protected void clearClassCache() {
        if (allowClasses != null) {
            allowClasses.clear();
        }
        if (disallowClasses != null) {
            disallowClasses.clear();
        }
    }
}