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

import flex.management.ManageableComponent;
import flex.management.runtime.messaging.endpoints.EndpointControl;
import flex.messaging.Destination;
import flex.messaging.FlexComponent;
import flex.messaging.FlexContext;
import flex.messaging.MessageBroker;
import flex.messaging.Server;
import flex.messaging.client.FlexClientManager;
import flex.messaging.cluster.ClusterManager;
import flex.messaging.endpoints.AbstractEndpoint;
import flex.messaging.endpoints.Endpoint;
import flex.messaging.endpoints.Endpoint2;
import flex.messaging.log.Log;
import flex.messaging.log.Target;
import flex.messaging.security.LoginCommand;
import flex.messaging.security.LoginManager;
import flex.messaging.services.AuthenticationService;
import flex.messaging.services.Service;
import flex.messaging.services.ServiceAdapter;
import flex.messaging.util.ClassUtil;
import flex.messaging.util.RedeployManager;
import flex.messaging.util.StringUtils;
import flex.messaging.util.ToStringPrettyPrinter;
import flex.messaging.util.UUIDGenerator;
import flex.messaging.validators.DeserializationValidator;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * This object encapsulates settings for a MessageBroker instance.
 * The MessageBroker itself has no knowledge of configuration specifics;
 * instead, this object sets the relevant values on the broker using
 * information which a ConfigurationParser has provided for it.
 */
public class MessagingConfiguration implements ServicesConfiguration {
    private final String asyncMessageBrokerType = "flex.messaging.AsyncMessageBroker";
    private final String asyncFlexClientManagerType = "flex.messaging.client.AsyncFlexClientManager";

    private final Map<String, ChannelSettings> channelSettings;
    private final List<String> defaultChannels;
    private final SecuritySettings securitySettings;
    private final List<ServiceSettings> serviceSettings;
    private final List<SharedServerSettings> sharedServerSettings;
    private LoggingSettings loggingSettings;
    private SystemSettings systemSettings;
    private FlexClientSettings flexClientSettings;
    private final Map<String, ClusterSettings> clusterSettings;
    private final Map<String, FactorySettings> factorySettings;
    private final List<MessageFilterSettings> messageFilterSettings;
    private final Map<String, ValidatorSettings> validatorSettings;

    /**
     * Constructor.
     * Construct a MessagingConfiguration object
     */
    public MessagingConfiguration() {
        channelSettings = new HashMap<String, ChannelSettings>();
        defaultChannels = new ArrayList<String>(4);
        clusterSettings = new HashMap<String, ClusterSettings>();
        factorySettings = new HashMap<String, FactorySettings>();
        serviceSettings = new ArrayList<ServiceSettings>();
        sharedServerSettings = new ArrayList<SharedServerSettings>();
        securitySettings = new SecuritySettings();
        messageFilterSettings = new ArrayList<MessageFilterSettings>();
        validatorSettings = new HashMap<String, ValidatorSettings>();
    }

    /**
     * Configure the MessageBroker.
     *
     * @param broker current MessageBroker object
     */
    public void configureBroker(MessageBroker broker) {
        boolean async = (broker.getClass().getName().equals(asyncMessageBrokerType));

        broker.setChannelSettings(channelSettings);
        broker.setSecuritySettings(securitySettings);
        broker.setSystemSettings(systemSettings);
        broker.setFlexClientSettings(flexClientSettings);

        // validators need to come first so that the other code can use them
        createValidators(broker);

        createAuthorizationManager(broker);
        createFlexClientManager(broker);
        createRedeployManager(broker);
        createFactories(broker);

        if (async)
            createSharedServers(broker);

        createEndpoints(broker);
        // Default channels have to be set after endpoints are created.
        broker.setDefaultChannels(defaultChannels);
        prepareClusters(broker);
        createServices(broker);

        if (async)
            createMessageFilters(broker);

        createUUIDGenerator(broker);
    }

    /**
     * Create a MessageBroker object with the Id.
     *
     * @param id     String the MessageBroker Id
     * @param loader the ClassLoader used to load the MessageBroker class
     * @return the created MessageBroker object
     */
    public MessageBroker createBroker(String id, ClassLoader loader) {
        // Construct MessageBroker with manageable constructor to avoid loading
        // any JMX classes in case manageable is set to false. 
        MessageBroker broker;
        try // Use the AsyncMessageBroker, if possible.
        {
            @SuppressWarnings("unchecked")
            Class<? extends MessageBroker> messageBrokerClass = ClassUtil.createClass(asyncMessageBrokerType, loader);
            Constructor constructor = messageBrokerClass.getConstructor(boolean.class);
            broker = (MessageBroker) constructor.newInstance(systemSettings.isManageable());
        } catch (Throwable t) // Otherwise, use the default MessageBroker.
        {
            broker = new MessageBroker(systemSettings.isManageable());
        }

        // Initialize MessageBroker.
        broker.setEnforceEndpointValidation(systemSettings.isEnforceEndpointValidation());
        //broker.setManaged(systemSettings.isManageable());
        broker.setId(id);
        broker.setClassLoader(loader);

        return broker;
    }

    private void createFactories(MessageBroker broker) {
        for (Iterator<Map.Entry<String, FactorySettings>> iter = factorySettings.entrySet().iterator(); iter.hasNext(); ) {
            Map.Entry<String, FactorySettings> entry = iter.next();
            String id = entry.getKey();
            FactorySettings factorySetting = entry.getValue();
            broker.addFactory(id, factorySetting.createFactory(broker.getClassLoader()));
        }
    }

    private void createFlexClientManager(MessageBroker broker) {
        FlexClientManager flexClientManager = null;
        try // Use the async version, if possible.
        {
            @SuppressWarnings("unchecked")
            Class<? extends FlexClientManager> flexClientManagerClass = ClassUtil.createClass(asyncFlexClientManagerType, broker.getClassLoader());
            Constructor ctor = flexClientManagerClass.getConstructor(broker.getClass());
            flexClientManager = (FlexClientManager) ctor.newInstance(broker);
        } catch (Throwable t) // Otherwise, use the default FlexClientManager.
        {
            flexClientManager = new FlexClientManager(broker.isManaged(), broker);
        }
        broker.setFlexClientManager(flexClientManager);
    }

    private void createRedeployManager(MessageBroker broker) {
        RedeployManager redeployManager = new RedeployManager();
        redeployManager.setEnabled(systemSettings.getRedeployEnabled());
        redeployManager.setWatchInterval(systemSettings.getWatchInterval());
        redeployManager.setTouchFiles(systemSettings.getTouchFiles());
        redeployManager.setWatchFiles(systemSettings.getWatchFiles());
        broker.setRedeployManager(redeployManager);
    }

    private void createAuthorizationManager(MessageBroker broker) {
        LoginManager loginManager = new LoginManager();

        // Create a Login Command for the LoginManager.
        LoginCommand loginCommand = null;

        Map loginCommands = securitySettings.getLoginCommands();

        // If default Login Command is enabled, use it.
        LoginCommandSettings loginCommandSettings = (LoginCommandSettings) loginCommands.get(LoginCommandSettings.SERVER_MATCH_OVERRIDE);
        if (loginCommandSettings != null) {
            loginCommand = initLoginCommand(loginCommandSettings);
        }
        // Otherwise, try a server specific Login Command.
        else {
            String serverInfo = securitySettings.getServerInfo();
            loginCommandSettings = (LoginCommandSettings) loginCommands.get(serverInfo);

            if (loginCommandSettings != null) {
                loginCommand = initLoginCommand(loginCommandSettings);
            } else {
                // Try a partial match of serverInfo
                serverInfo = serverInfo.toLowerCase();
                for (Iterator iterator = loginCommands.keySet().iterator(); iterator.hasNext(); ) {
                    String serverMatch = (String) iterator.next();
                    loginCommandSettings = (LoginCommandSettings) loginCommands.get(serverMatch);

                    if (serverInfo.indexOf(serverMatch.toLowerCase()) != -1) {
                        // add this match for easier lookup next time around
                        loginCommands.put(serverInfo, loginCommandSettings);
                        loginCommand = initLoginCommand(loginCommandSettings);
                        break;
                    }
                }
            }
        }

        if (loginCommand == null) {
            if (Log.isWarn())
                Log.getLogger(ConfigurationManager.LOG_CATEGORY).warn
                        ("No login command was found for '" + securitySettings.getServerInfo()
                                + "'. Please ensure that the login-command tag has the correct server attribute value"
                                + ", or use 'all' to use the login command regardless of the server.");
        } else {
            loginManager.setLoginCommand(loginCommand);
        }

        if (loginCommandSettings != null)
            loginManager.setPerClientAuthentication(loginCommandSettings.isPerClientAuthentication());

        broker.setLoginManager(loginManager);
    }

    private LoginCommand initLoginCommand(LoginCommandSettings loginCommandSettings) {
        String loginClass = loginCommandSettings.getClassName();
        Class c = ClassUtil.createClass(loginClass,
                FlexContext.getMessageBroker() == null ? null :
                        FlexContext.getMessageBroker().getClassLoader());
        LoginCommand loginCommand = (LoginCommand) ClassUtil.createDefaultInstance(c, LoginCommand.class);

        return loginCommand;
    }

    private void createSharedServers(MessageBroker broker) {
        for (SharedServerSettings settings : sharedServerSettings) {
            String id = settings.getId();
            String className = settings.getClassName();
            Class serverClass = ClassUtil.createClass(className, broker.getClassLoader());
            FlexComponent server = (FlexComponent) ClassUtil.createDefaultInstance(serverClass, serverClass);
            server.initialize(id, settings.getProperties());
            if (broker.isManaged() && (server instanceof ManageableComponent)) {
                ManageableComponent manageableServer = (ManageableComponent) server;
                manageableServer.setManaged(true);
                manageableServer.setParent(broker);
            }

            // TODO: move this to only AsyncMessageBroker.
            broker.addServer((Server) server);

            if (Log.isInfo()) {
                Log.getLogger(ConfigurationManager.LOG_CATEGORY).info
                        ("Server '" + id + "' of type '" + className + "' created.");
            }
        }
    }

    private void createEndpoints(MessageBroker broker) {
        for (Iterator<String> iter = channelSettings.keySet().iterator(); iter.hasNext(); ) {
            String id = iter.next();
            ChannelSettings chanSettings = channelSettings.get(id);
            String url = chanSettings.getUri();
            String endpointClassName = chanSettings.getEndpointType();

            // Create the Endpoint
            Endpoint endpoint = broker.createEndpoint(id, url, endpointClassName);

            // Cast to AbstractEndpoint - these are newer properties that post-date the locked Endpoint interface.
            if (endpoint instanceof AbstractEndpoint) {
                AbstractEndpoint abstractEndpoint = (AbstractEndpoint) endpoint;
                abstractEndpoint.setRemote(chanSettings.isRemote());
                abstractEndpoint.setServerOnly(chanSettings.getServerOnly());
            }

            endpoint.setSecurityConstraint(chanSettings.getConstraint());
            endpoint.setClientType(chanSettings.getClientType());

            // Assign referenced server
            String referencedServerId = chanSettings.getServerId();
            if ((referencedServerId != null) && (endpoint instanceof Endpoint2)) {
                Server server = broker.getServer(referencedServerId);
                if (server == null) {
                    ConfigurationException ce = new ConfigurationException();
                    ce.setMessage(11128, new Object[]{chanSettings.getId(), referencedServerId});
                    throw ce;
                }
                ((Endpoint2) endpoint).setServer(broker.getServer(referencedServerId));
            }

            // Initialize with endpoint properties
            endpoint.initialize(id, chanSettings.getProperties());

            if (Log.isInfo()) {
                String endpointURL = endpoint.getUrl();
                String endpointSecurity = EndpointControl.getSecurityConstraintOf(endpoint);
                if (StringUtils.isEmpty(endpointSecurity))
                    endpointSecurity = "None";
                Log.getLogger(ConfigurationManager.LOG_CATEGORY).info
                        ("Endpoint '" + id + "' created with security: " +
                                endpointSecurity + StringUtils.NEWLINE +
                                "at URL: " + endpointURL);
            }
        }
    }

    private void createServices(MessageBroker broker) {
        //the broker needs its AuthenticationService always
        AuthenticationService authService = new AuthenticationService();
        authService.setMessageBroker(broker);

        for (Iterator<ServiceSettings> iter = serviceSettings.iterator(); iter.hasNext(); ) {
            ServiceSettings svcSettings = iter.next();
            String svcId = svcSettings.getId();
            String svcClassName = svcSettings.getClassName();

            // Create the Service
            Service service = broker.createService(svcId, svcClassName);

            // Service Class Name - not needed in AbstractService

            // Initialize with service properties
            service.initialize(svcId, svcSettings.getProperties());

            // Default Channels
            for (Iterator chanIter = svcSettings.getDefaultChannels().iterator(); chanIter.hasNext(); ) {
                ChannelSettings chanSettings = (ChannelSettings) chanIter.next();
                service.addDefaultChannel(chanSettings.getId());
            }

            // Adapter Definitions
            Map svcAdapterSettings = svcSettings.getAllAdapterSettings();
            for (Iterator asIter = svcAdapterSettings.values().iterator(); asIter.hasNext(); ) {
                AdapterSettings as = (AdapterSettings) asIter.next();
                service.registerAdapter(as.getId(), as.getClassName());
                if (as.isDefault()) {
                    service.setDefaultAdapter(as.getId());
                }
            }

            // Destinations
            Map destinationSettings = svcSettings.getDestinationSettings();
            for (Iterator destSettingsIter = destinationSettings.keySet().iterator(); destSettingsIter.hasNext(); ) {
                String destName = (String) destSettingsIter.next();
                DestinationSettings destSettings = (DestinationSettings) destinationSettings.get(destName);

                createDestination(destSettings, service, svcSettings);
            }
        }
    }

    private void createDestination(DestinationSettings destSettings, Service service, ServiceSettings svcSettings) {
        String destId = destSettings.getId();
        Destination destination = service.createDestination(destId);

        // Channels
        List chanSettings = destSettings.getChannelSettings();
        if (chanSettings.size() > 0) {
            List<String> channelIds = new ArrayList<String>(2);
            for (Iterator iter = chanSettings.iterator(); iter.hasNext(); ) {
                ChannelSettings cs = (ChannelSettings) iter.next();
                channelIds.add(cs.getId());
            }
            destination.setChannels(channelIds);
        }

        // Security
        SecurityConstraint constraint = destSettings.getConstraint();
        destination.setSecurityConstraint(constraint);

        // Initialize with service, adapter and destination properties
        destination.initialize(destId, svcSettings.getProperties());
        destination.initialize(destId, destSettings.getAdapterSettings().getProperties());
        destination.initialize(destId, destSettings.getProperties());

        // Service Adapter
        createAdapter(destination, destSettings, svcSettings);
    }

    private void createAdapter(Destination destination, DestinationSettings destSettings, ServiceSettings svcSettings) {
        AdapterSettings adapterSettings = destSettings.getAdapterSettings();
        String adapterId = adapterSettings.getId();

        ServiceAdapter adapter = destination.createAdapter(adapterId);

        // Initialize with service, adapter and then destination properties
        adapter.initialize(adapterId, svcSettings.getProperties());
        adapter.initialize(adapterId, adapterSettings.getProperties());
        adapter.initialize(adapterId, destSettings.getProperties());

    }

    /**
     * Used by the MessageBrokerServlet to set up the singleton Log instance
     * and add any targets defined in the logging configuration.
     * This needs to be invoked ahead of creating and bootstrapping a MessageBroker
     * instance so we're sure to have the logging system running in case the bootstrap
     * process needs to log anything out.
     */
    public void createLogAndTargets() {
        if (loggingSettings == null) {
            Log.setPrettyPrinterClass(ToStringPrettyPrinter.class.getName());
            return;
        }

        Log.createLog();

        ConfigMap properties = loggingSettings.getProperties();

        // Override default pretty printer for FDS to traverse deep Object graphs
        if (properties.getPropertyAsString("pretty-printer", null) == null) {
            Log.setPrettyPrinterClass(ToStringPrettyPrinter.class.getName());
        }

        Log.initialize(null, properties);

        // Targets
        List targets = loggingSettings.getTargets();
        Iterator it = targets.iterator();
        while (it.hasNext()) {
            TargetSettings targetSettings = (TargetSettings) it.next();
            String className = targetSettings.getClassName();

            Class c = ClassUtil.createClass(className,
                    FlexContext.getMessageBroker() == null ? null :
                            FlexContext.getMessageBroker().getClassLoader());
            try {
                Target target = (Target) c.newInstance();
                target.setLevel(Log.readLevel(targetSettings.getLevel()));
                target.setFilters(targetSettings.getFilters());
                target.initialize(null, targetSettings.getProperties());
                Log.addTarget(target);
            } catch (Throwable t) {
                // Unwrap to get to the interesting exception
                if (t instanceof InvocationTargetException)
                    t = t.getCause();

                System.err.println("*** Error setting up logging system");
                t.printStackTrace();

                ConfigurationException cx = new ConfigurationException();
                cx.setMessage(10126, new Object[]{className});
                cx.setRootCause(t);
                throw cx;
            }
        }
    }

    private void createMessageFilters(MessageBroker broker) {
        Class asyncFilterClass = ClassUtil.createClass("flex.messaging.filters.BaseAsyncMessageFilter");
        Class syncFilterClass = ClassUtil.createClass("flex.messaging.filters.BaseSyncMessageFilter");

        for (MessageFilterSettings settings : messageFilterSettings) {
            String id = settings.getId();
            String className = settings.getClassName();
            Class filterClass = ClassUtil.createClass(className, broker.getClassLoader());
            FlexComponent filter = (FlexComponent) ClassUtil.createDefaultInstance(filterClass, null);
            MessageFilterSettings.FilterType filterType = settings.getFilterType();
            boolean filterIsAsync = filterType == MessageFilterSettings.FilterType.ASYNC;
            // Validate filter is assignable to proper base class.
            if ((filterIsAsync && !asyncFilterClass.isAssignableFrom(filterClass)) ||
                    (!filterIsAsync && !syncFilterClass.isAssignableFrom(filterClass))) {
                // Filter class is not a valid subclass of either supported base filter type.
                ConfigurationException cx = new ConfigurationException();
                int errorCode = filterIsAsync ? 11144 : 11145;
                cx.setMessage(errorCode, new Object[]{settings.getId()});
                throw cx;
            }

            filter.initialize(id, settings.getProperties());
            if (broker.isManaged() && (filter instanceof ManageableComponent)) {
                ManageableComponent manageableFilter = (ManageableComponent) filter;
                manageableFilter.setManaged(true);
                manageableFilter.setParent(broker);
            }

            try {
                String methodName = filterIsAsync ? "getAsyncMessageFilterChain" : "getSyncMessageFilterChain";
                Method getMessageFilterChain = broker.getClass().getDeclaredMethod(methodName);
                Object filterChain = getMessageFilterChain.invoke(broker, (Object[]) null);
                Class arg = filterIsAsync ? asyncFilterClass : syncFilterClass;
                Method addFilter = filterChain.getClass().getDeclaredMethod("add", arg);
                addFilter.invoke(filterChain, filter);
            } catch (Exception e) {
                // Hit an unexpected problem adding the filter instance to the broker's async or sync chain.
                ConfigurationException cx = new ConfigurationException();
                int errorCode = filterType == MessageFilterSettings.FilterType.ASYNC ? 11138 : 11143;
                cx.setMessage(errorCode, new Object[]{settings.getId()});
                cx.setRootCause(e);
                throw cx;
            }

            if (Log.isInfo()) {
                Log.getLogger(ConfigurationManager.LOG_CATEGORY).info
                        ("MessageFilter '" + id + "' of type '" + className + "' created.");
            }
        }
    }

    private void createValidators(MessageBroker broker) {
        for (Iterator<ValidatorSettings> iter = validatorSettings.values().iterator(); iter.hasNext(); ) {
            ValidatorSettings settings = iter.next();
            String className = settings.getClassName();
            String type = settings.getType();
            Class<?> validatorClass = ClassUtil.createClass(className, broker.getClassLoader());
            Class<?> expectedClass = ClassUtil.createClass(type, broker.getClassLoader());
            Object validator = ClassUtil.createDefaultInstance(validatorClass, expectedClass);
            // Only set the DeserializationValidator types for now.
            if (validator instanceof DeserializationValidator) {
                DeserializationValidator deserializationValidator = (DeserializationValidator) validator;
                deserializationValidator.initialize(null, settings.getProperties());
                broker.setDeserializationValidator(deserializationValidator);
                if (Log.isInfo()) {
                    Log.getLogger(ConfigurationManager.LOG_CATEGORY).info
                            ("DeserializationValidator of type '" + className + "' created.");
                }
            }
        }
    }

    private void createUUIDGenerator(MessageBroker broker) {
        String className = systemSettings.getUUIDGeneratorClassName();
        if (className == null || className.length() == 0)
            return;

        Class uuidGeneratorClass = ClassUtil.createClass(className, broker.getClassLoader());
        if (!UUIDGenerator.class.isAssignableFrom(uuidGeneratorClass)) {
            // UUID Generator class is not a valid subclass of ''{0}''
            ConfigurationException cx = new ConfigurationException();
            cx.setMessage(11148, new Object[]{UUIDGenerator.class.getName()});
            throw cx;
        }

        Object uuidGenerator = ClassUtil.createDefaultInstance(uuidGeneratorClass, UUIDGenerator.class);
        broker.setUUIDGenerator((UUIDGenerator) uuidGenerator);
    }

    private void prepareClusters(MessageBroker broker) {
        ClusterManager clusterManager = broker.getClusterManager();
        for (Iterator<String> iter = clusterSettings.keySet().iterator(); iter.hasNext(); ) {
            String clusterId = iter.next();
            ClusterSettings cs = clusterSettings.get(clusterId);
            clusterManager.prepareCluster(cs);
        }
    }

    /**
     * Add Shared Server configurations.
     *
     * @param settings the SharedServerSettings object
     **/
    public void addSharedServerSettings(SharedServerSettings settings) {
        sharedServerSettings.add(settings);
    }

    /**
     * Add the Channel configurations.
     *
     * @param id       the ChannelSetting Id
     * @param settings the ChannelSettings
     **/
    public void addChannelSettings(String id, ChannelSettings settings) {
        channelSettings.put(id, settings);
    }

    /**
     * Get the ChannelSettings by Id.
     *
     * @param id the ChannelSettings Id
     * @return ChannelSettings the Channel settings
     **/
    public ChannelSettings getChannelSettings(String id) {
        return channelSettings.get(id);
    }

    /**
     * Get all the ChannelSettings.
     *
     * @return Map the Map of all the ChannelSettings, maped by Id
     **/
    public Map getAllChannelSettings() {
        return channelSettings;
    }

    /**
     * Add the default Channel by Id.
     *
     * @param id the Channel Id
     **/
    public void addDefaultChannel(String id) {
        defaultChannels.add(id);
    }

    /**
     * Get the default Channel List.
     *
     * @return List, the list of default Channels
     **/
    public List getDefaultChannels() {
        return defaultChannels;
    }

    /**
     * Get the Security Configurations.
     *
     * @return SecuritySettings current SecuritySettings
     **/
    public SecuritySettings getSecuritySettings() {
        return securitySettings;
    }

    /**
     * Add Service Configurations.
     *
     * @param settings the ServiceSettings object
     **/
    public void addServiceSettings(ServiceSettings settings) {
        serviceSettings.add(settings);
    }

    /**
     * Get ServiceSettings by Id.
     *
     * @param id the ServiceSettings Id
     * @return ServiceSettings the ServiceSettings object
     **/
    public ServiceSettings getServiceSettings(String id) {
        for (Iterator<ServiceSettings> iter = serviceSettings.iterator(); iter.hasNext(); ) {
            ServiceSettings serviceSettings = iter.next();
            if (serviceSettings.getId().equals(id))
                return serviceSettings;
        }
        return null;
    }

    /**
     * Get all ServiceSettings.
     *
     * @return List all the service settings
     **/
    public List getAllServiceSettings() {
        return serviceSettings;
    }

    /**
     * Get LoggingSettings.
     *
     * @return LoggingSettings the LoggingSettings object
     **/
    public LoggingSettings getLoggingSettings() {
        return loggingSettings;
    }

    /**
     * Set LoggingSettings.
     *
     * @param loggingSettings the LoggingSettings object
     **/
    public void setLoggingSettings(LoggingSettings loggingSettings) {
        this.loggingSettings = loggingSettings;
    }

    /**
     * Set SystemSettings.
     *
     * @param ss the SystemSettings object
     **/
    public void setSystemSettings(SystemSettings ss) {
        systemSettings = ss;
    }

    /**
     * Get SystemSettings.
     *
     * @return SystemSettings the LoggingSettings object
     **/
    public SystemSettings getSystemSettings() {
        return systemSettings;
    }

    /**
     * Set FlexClientSettings.
     *
     * @param value the FlexClientSettings object
     **/
    public void setFlexClientSettings(FlexClientSettings value) {
        flexClientSettings = value;
    }

    /**
     * Get FlexClientSettings.
     *
     * @return FlexClientSettings the FlexClientSettings object
     **/
    public FlexClientSettings getFlexClientSettings() {
        return flexClientSettings;
    }

    /**
     * Add the ClusterSettings.
     *
     * @param settings the ClusterSettings object
     **/
    public void addClusterSettings(ClusterSettings settings) {
        if (settings.isDefault()) {
            for (Iterator<ClusterSettings> it = clusterSettings.values().iterator(); it.hasNext(); ) {
                ClusterSettings cs = it.next();

                if (cs.isDefault()) {
                    ConfigurationException cx = new ConfigurationException();
                    cx.setMessage(10214, new Object[]{settings.getClusterName(), cs.getClusterName()});
                    throw cx;
                }
            }
        }
        if (clusterSettings.containsKey(settings.getClusterName())) {
            ConfigurationException cx = new ConfigurationException();
            cx.setMessage(10206, new Object[]{settings.getClusterName()});
            throw cx;
        }
        clusterSettings.put(settings.getClusterName(), settings);
    }

    /**
     * Get the ClusterSettings object by Id.
     *
     * @param clusterId the ClusterSettings Id
     * @return ClusterSettings the ClusterSettings object
     **/
    public ClusterSettings getClusterSettings(String clusterId) {
        for (Iterator<ClusterSettings> it = clusterSettings.values().iterator(); it.hasNext(); ) {
            ClusterSettings cs = it.next();
            if (cs.getClusterName() == clusterId)
                return cs; // handle null case
            if (cs.getClusterName() != null && cs.getClusterName().equals(clusterId))
                return cs;
        }
        return null;
    }

    /**
     * Get the default ClusterSettings.
     *
     * @return ClusterSettings the default ClusterSetting object
     **/
    public ClusterSettings getDefaultCluster() {
        for (Iterator<ClusterSettings> it = clusterSettings.values().iterator(); it.hasNext(); ) {
            ClusterSettings cs = it.next();
            if (cs.isDefault())
                return cs;
        }
        return null;
    }

    /**
     * Add FactorySettings by Id.
     *
     * @param id       the FactorySettings Id
     * @param settings the FactorySettings object
     **/
    public void addFactorySettings(String id, FactorySettings settings) {
        factorySettings.put(id, settings);
    }

    /**
     * Add MessageFilterSettings.
     *
     * @param settings the MessageFilterSettings object
     **/
    public void addMessageFilterSettings(MessageFilterSettings settings) {
        messageFilterSettings.add(settings);
    }

    /**
     * Add ValidatorSettings.
     *
     * @param settings the ValidatorSettings object
     **/
    public void addValidatorSettings(ValidatorSettings settings) {
        String type = settings.getType();
        if (validatorSettings.containsKey(type)) {
            // Cannot add multiple validators with the same type ''{0}''
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(11136, new Object[]{type});
            throw ce;
        }
        validatorSettings.put(type, settings);
    }

    /**
     * Report unused properties.
     **/
    public void reportUnusedProperties() {
        ArrayList<Object[]> findings = new ArrayList<Object[]>();

        Iterator<ServiceSettings> serviceItr = serviceSettings.iterator();
        while (serviceItr.hasNext()) {
            ServiceSettings serviceSettings = serviceItr.next();
            gatherUnusedProperties(serviceSettings.getId(), serviceSettings.getSourceFile(),
                    ConfigurationConstants.SERVICE_ELEMENT, serviceSettings, findings);
            Iterator destinationItr = serviceSettings.getDestinationSettings().values().iterator();
            while (destinationItr.hasNext()) {
                DestinationSettings destinationSettings = (DestinationSettings) destinationItr.next();
                gatherUnusedProperties(destinationSettings.getId(), destinationSettings.getSourceFile(),
                        ConfigurationConstants.DESTINATION_ELEMENT,
                        destinationSettings, findings);

                AdapterSettings adapterSettings = destinationSettings.getAdapterSettings();
                if (adapterSettings != null) {
                    gatherUnusedProperties(adapterSettings.getId(), adapterSettings.getSourceFile(),
                            ConfigurationConstants.ADAPTER_ELEMENT,
                            adapterSettings, findings);
                }
            }
        }

        Iterator<ChannelSettings> channelItr = channelSettings.values().iterator();
        while (channelItr.hasNext()) {
            ChannelSettings channelSettings = channelItr.next();
            // Skip property validation for remote channel-definitions
            if (channelSettings.isRemote())
                continue;

            gatherUnusedProperties(channelSettings.getId(), channelSettings.getSourceFile(),
                    ConfigurationConstants.CHANNEL_ELEMENT, channelSettings, findings);
        }

        Iterator<SharedServerSettings> serverItr = sharedServerSettings.iterator();
        while (serverItr.hasNext()) {
            SharedServerSettings serverSettings = serverItr.next();
            gatherUnusedProperties(serverSettings.getId(), serverSettings.getSourceFile(),
                    ConfigurationConstants.SERVER_ELEMENT, serverSettings, findings);
        }

        if (!findings.isEmpty()) {
            int errorNumber = 10149;
            ConfigurationException exception = new ConfigurationException();
            StringBuffer allDetails = new StringBuffer();
            for (int i = 0; i < findings.size(); i++) {
                allDetails.append(StringUtils.NEWLINE);
                allDetails.append("  ");
                exception.setDetails(errorNumber, "pattern", findings.get(i));
                allDetails.append(exception.getDetails());
                exception.setDetails(null);
            }
            exception.setMessage(errorNumber, new Object[]{allDetails});
            throw exception;
        }
    }

    private void gatherUnusedProperties
            (String settingsId, String settingsSource, String settingsType,
             PropertiesSettings settings, Collection<Object[]> result) {
        List unusedProperties = settings.getProperties().findAllUnusedProperties();
        int size = unusedProperties.size();
        if (size > 0) {
            for (int i = 0; i < size; i++) {
                String path = (String) unusedProperties.get(i);
                result.add(new Object[]{path, settingsType, settingsId, settingsSource});
            }
        }
    }
}
