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

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.clustering.ClusteringAgent;
import org.apache.axis2.clustering.ClusteringConstants;
import org.apache.axis2.clustering.Member;
import org.apache.axis2.clustering.management.GroupManagementAgent;
import org.apache.axis2.clustering.management.NodeManager;
import org.apache.axis2.clustering.state.StateManager;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.i18n.Messages;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * Builds the cluster configuration from the axis2.xml file
 */
public class ClusterBuilder extends DescriptionBuilder {

    private static final Log log = LogFactory.getLog(ClusterBuilder.class);

    public ClusterBuilder(AxisConfiguration axisConfig) {
        this.axisConfig = axisConfig;
    }

    /**
     * Build the cluster configuration
     *
     * @param clusterElement Cluster element
     * @throws DeploymentException If an error occurs while building the cluster configuration
     */
    public void buildCluster(OMElement clusterElement) throws DeploymentException {

        if (!isEnabled(clusterElement)) {
            log.info("Clustering has been disabled");
            return;
        }
        log.info("Clustering has been enabled");

        OMAttribute classNameAttr = clusterElement.getAttribute(new QName(TAG_CLASS_NAME));
        if (classNameAttr == null) {
            throw new DeploymentException(Messages.getMessage("classAttributeNotFound",
                                                              TAG_CLUSTER));
        }

        String className = classNameAttr.getAttributeValue();
        ClusteringAgent clusteringAgent;
        try {
            Class clazz;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new DeploymentException(Messages.getMessage("clusterImplNotFound",
                                                                  className));
            }
            clusteringAgent = (ClusteringAgent) clazz.newInstance();

            clusteringAgent.setConfigurationContext(configCtx);

            //loading the parameters.
            processParameters(clusterElement.getChildrenWithName(new QName(TAG_PARAMETER)),
                              clusteringAgent,
                              null);

            // loading the application domains
            loadGroupManagement(clusteringAgent, clusterElement);

            // loading the members
            loadWellKnownMembers(clusteringAgent, clusterElement);

            //loading the NodeManager
            loadNodeManager(clusterElement, clusteringAgent);

            // loading the StateManager
            loadStateManager(clusterElement, clusteringAgent);

            axisConfig.setClusteringAgent(clusteringAgent);
        } catch (InstantiationException e) {
            throw new DeploymentException(Messages.getMessage("cannotLoadClusterImpl"));
        } catch (IllegalAccessException e) {
            throw new DeploymentException(e);
        }
    }

    private boolean isEnabled(OMElement element) {
        boolean enabled = true;
        OMAttribute enableAttr = element.getAttribute(new QName("enable"));
        if (enableAttr != null) {
            enabled = Boolean.parseBoolean(enableAttr.getAttributeValue().trim());
        }
        return enabled;
    }

    private void loadGroupManagement(ClusteringAgent clusteringAgent,
                                     OMElement clusterElement) throws DeploymentException {
        OMElement lbEle = clusterElement.getFirstChildWithName(new QName("groupManagement"));
        if (lbEle != null) {
            if (isEnabled(lbEle)) {
                log.info("Running in group management mode");
            } else {
                log.info("Running in application mode");
                return;
            }

            for (Iterator iter = lbEle.getChildrenWithName(new QName("applicationDomain"));
                 iter.hasNext();) {
                OMElement omElement = (OMElement) iter.next();
                String domainName = omElement.getAttributeValue(new QName("name")).trim();
                String handlerClass = omElement.getAttributeValue(new QName("agent")).trim();
                String descAttrib = omElement.getAttributeValue(new QName("description"));
                String description = "Description not found";
                if (descAttrib != null) {
                    description = descAttrib.trim();
                }
                GroupManagementAgent eventHandler;
                try {
                    eventHandler = (GroupManagementAgent) Class.forName(handlerClass).newInstance();
                    eventHandler.setDescription(description);
                } catch (Exception e) {
                    String msg = "Could not instantiate GroupManagementAgent " + handlerClass +
                                 " for domain " + domainName;
                    log.error(msg, e);
                    throw new DeploymentException(msg, e);
                }
                clusteringAgent.addGroupManagementAgent(eventHandler, domainName);
            }
        }
    }

    private void loadWellKnownMembers(ClusteringAgent clusteringAgent, OMElement clusterElement) {
        clusteringAgent.setMembers(new ArrayList<Member>());
        Parameter membershipSchemeParam = clusteringAgent.getParameter("membershipScheme");
        if (membershipSchemeParam != null) {
            String membershipScheme = ((String) membershipSchemeParam.getValue()).trim();
            if (membershipScheme.equals(ClusteringConstants.MembershipScheme.WKA_BASED)) {
                List<Member> members = new ArrayList<Member>();
                OMElement membersEle =
                        clusterElement.getFirstChildWithName(new QName("members"));
                if (membersEle != null) {
                    for (Iterator iter = membersEle.getChildrenWithLocalName("member"); iter.hasNext();) {
                        OMElement memberEle = (OMElement) iter.next();
                        String hostName =
                                memberEle.getFirstChildWithName(new QName("hostName")).getText().trim();
                        String port =
                                memberEle.getFirstChildWithName(new QName("port")).getText().trim();
                        members.add(new Member(replaceVariables(hostName),
                                               Integer.parseInt(replaceVariables(port))));
                    }
                }
                clusteringAgent.setMembers(members);
            }
        }
    }

    private String replaceVariables(String text) {
        int indexOfStartingChars;
        int indexOfClosingBrace;

        // The following condition deals with properties.
        // Properties are specified as ${system.property},
        // and are assumed to be System properties
        if ((indexOfStartingChars = text.indexOf("${")) != -1 &&
            (indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a property used?
            String var = text.substring(indexOfStartingChars + 2,
                                        indexOfClosingBrace);

            String propValue = System.getProperty(var);
            if (propValue == null) {
                propValue = System.getenv(var);
            }
            if (propValue != null) {
                text = text.substring(0, indexOfStartingChars) + propValue +
                       text.substring(indexOfClosingBrace + 1);
            }
        }
        return text;
    }

    private void loadStateManager(OMElement clusterElement,
                                    ClusteringAgent clusteringAgent) throws DeploymentException,
                                                                          InstantiationException,
                                                                          IllegalAccessException {
        OMElement contextManagerEle =
                clusterElement.getFirstChildWithName(new QName(TAG_STATE_MANAGER));
        if (contextManagerEle != null) {
            if (!isEnabled(contextManagerEle)) {
                log.info("Clustering state management has been disabled");
                return;
            }
            log.info("Clustering state management has been enabled");

            // Load & set the StateManager class
            OMAttribute classNameAttr =
                    contextManagerEle.getAttribute(new QName(ATTRIBUTE_CLASS));
            if (classNameAttr == null) {
                throw new DeploymentException(Messages.getMessage("classAttributeNotFound",
                                                                  TAG_STATE_MANAGER));
            }

            String className = classNameAttr.getAttributeValue();

            Class clazz;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new DeploymentException(Messages.getMessage("clusterImplNotFound",
                                                                  className));
            }
            StateManager stateManager = (StateManager) clazz.newInstance();
            clusteringAgent.setStateManager(stateManager);

            //loading the parameters.
            processParameters(contextManagerEle.getChildrenWithName(new QName(TAG_PARAMETER)),
                              stateManager,
                              null);

            // Load the replication patterns to be excluded. We load the following structure.
            /*<replication>
                <defaults>
                    <exclude name="foo.bar.*"/>
                </defaults>
                <context class="org.apache.axis2.context.ConfigurationContext">
                    <exclude name="my.sandesha.*"/>
                </context>
                <context class="org.apache.axis2.context.ServiceGroupContext">
                    <exclude name="my.sandesha.*"/>
                </context>
                <context class="org.apache.axis2.context.ServiceContext">
                    <exclude name="my.sandesha.*"/>
                </context>
            </replication>*/
            OMElement replicationEle =
                    contextManagerEle.getFirstChildWithName(new QName(TAG_REPLICATION));
            if (replicationEle != null) {
                // Process defaults
                OMElement defaultsEle =
                        replicationEle.getFirstChildWithName(new QName(TAG_DEFAULTS));
                if (defaultsEle != null) {
                    List<String> defaults = new ArrayList<String>();
                    for (Iterator iter = defaultsEle.getChildrenWithName(new QName(TAG_EXCLUDE));
                         iter.hasNext();) {
                        OMElement excludeEle = (OMElement) iter.next();
                        OMAttribute nameAtt = excludeEle.getAttribute(new QName(ATTRIBUTE_NAME));
                        defaults.add(nameAtt.getAttributeValue());
                    }
                    stateManager.setReplicationExcludePatterns(TAG_DEFAULTS, defaults);
                }

                // Process specifics
                for (Iterator iter = replicationEle.getChildrenWithName(new QName(TAG_CONTEXT));
                     iter.hasNext();) {
                    OMElement contextEle = (OMElement) iter.next();
                    String ctxClassName =
                            contextEle.getAttribute(new QName(ATTRIBUTE_CLASS)).getAttributeValue();
                    List<String> excludes = new ArrayList<String>();
                    for (Iterator iter2 = contextEle.getChildrenWithName(new QName(TAG_EXCLUDE));
                         iter2.hasNext();) {
                        OMElement excludeEle = (OMElement) iter2.next();
                        OMAttribute nameAtt = excludeEle.getAttribute(new QName(ATTRIBUTE_NAME));
                        excludes.add(nameAtt.getAttributeValue());
                    }
                    stateManager.setReplicationExcludePatterns(ctxClassName, excludes);
                }
            }
        }
    }

    private void loadNodeManager(OMElement clusterElement,
                                   ClusteringAgent clusteringAgent) throws DeploymentException,
                                                                         InstantiationException,
                                                                         IllegalAccessException {
        OMElement configManagerEle =
                clusterElement.getFirstChildWithName(new QName(TAG_NODE_MANAGER));
        if (configManagerEle != null) {
            if (!isEnabled(configManagerEle)) {
                log.info("Clustering configuration management has been disabled");
                return;
            }
            log.info("Clustering configuration management has been enabled");

            OMAttribute classNameAttr = configManagerEle.getAttribute(new QName(ATTRIBUTE_CLASS));
            if (classNameAttr == null) {
                throw new DeploymentException(Messages.getMessage("classAttributeNotFound",
                                                                  TAG_NODE_MANAGER));
            }

            String className = classNameAttr.getAttributeValue();
            Class clazz;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new DeploymentException(Messages.getMessage("clusterImplNotFound",
                                                                  className));
            }

            NodeManager nodeManager = (NodeManager) clazz.newInstance();
            clusteringAgent.setNodeManager(nodeManager);

            //updating the NodeManager with the new ConfigurationContext
            nodeManager.setConfigurationContext(configCtx);

            //loading the parameters.
            processParameters(configManagerEle.getChildrenWithName(new QName(TAG_PARAMETER)),
                              nodeManager,
                              null);
        }
    }
}
