/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.webapp.jonasadmin;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Hashtable;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionServlet;
import org.ow2.jonas.lib.bootstrap.JProp;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.lib.util.ConfigurationConstants;
import org.ow2.jonas.lib.util.JonasObjectName;
import org.ow2.jonas.webapp.jonasadmin.common.CatalinaObjectName;
import org.ow2.jonas.webapp.jonasadmin.domain.ServerItem;
import org.ow2.jonas.webapp.taglib.TreeControl;
import org.ow2.jonas.webapp.taglib.TreeControlNode;


/**
 * @author Michel-Ange ANTON
 */
/**
 * @author eyindanga
 */
public class WhereAreYou {

//	--------------------------------------------------------- Public Constants
    /**
     * Exceptions
     */
    public final static String EXCEPTION_MBEANSERVER_NOTFOUND = "error.mbeanserver.notfound";
    public final static String EXCEPTION_JONASSERVER_NOTFOUND = "error.jonasserver.notfound";
    public final static String EXCEPTION_MBEAN_J2EEDOMAIN_NOTFOUND = "error.mbean.j2eedomain.notfound";
    public final static String EXCEPTION_MBEAN_J2EESERVER_NOTFOUND = "error.mbean.j2eeserver.notfound";

    /**
     * Name of the variable in http session
     */
    public final static String SESSION_NAME = "WhereAreYou";

    // Constant environnement
    public final static String TAGS_IMAGES_ROOT_KEY = "tagsimagesroot";
    public final static String CONTEXT_MACRO = "${CONTEXT}";
    public final static String TREE_PAGE_REFRESH = "viewTree.do?select=";

    /**
     * Used separator in the ident node in the tree
     */
    public final static String NODE_SEPARATOR = "*";

    // Deployment identification number
    public final static int DEPLOYMENT = 0;
    public final static int DEPLOYMENT_EAR = 1;
    public final static int DEPLOYMENT_JAR = 2;
    public final static int DEPLOYMENT_WAR = 3;
    public final static int DEPLOYMENT_RAR = 4;
    public final static int DEPLOYMENT_DATASOURCE = 5;
    public final static int DEPLOYMENT_JMS = 6;
    public final static int DEPLOYMENT_MAIL = 7;

    // Deployment identification number for domain management
    public final static int DOMAIN_DEPLOYMENT_EAR = 8;
    public final static int DOMAIN_DEPLOYMENT_JAR = 9;
    public final static int DOMAIN_DEPLOYMENT_WAR = 10;
    public final static int DOMAIN_DEPLOYMENT_RAR = 11;

    // Deployment identification string
    public final static String DEPLOYMENT_STRING_EAR = "ear";
    public final static String DEPLOYMENT_STRING_JAR = "jar";
    public final static String DEPLOYMENT_STRING_WAR = "war";
    public final static String DEPLOYMENT_STRING_RAR = "rar";
    public final static String DEPLOYMENT_STRING = "*";
    public final static String DEPLOYMENT_STRING_DATASOURCE = "datasource";
    public final static String DEPLOYMENT_STRING_JMS = "jms";
    public final static String DEPLOYMENT_STRING_MAILFACTORY = "mail";

//	Deployment identification strings for domain management
    public final static String DOMAIN_DEPLOYMENT_STRING_EAR = "domain-ear";
    public final static String DOMAIN_DEPLOYMENT_STRING_JAR = "domain-jar";
    public final static String DOMAIN_DEPLOYMENT_STRING_WAR = "domain-war";
    public final static String DOMAIN_DEPLOYMENT_STRING_RAR = "domain-rar";


//	--------------------------------------------------------- Properties variable

    private String imagesRoot = null;
    private TreeControl treeControl = null;
    private boolean treeToRefresh = false;

    private int applicationServerPort = 0;
    private String applicationContextPath = null;

    private boolean catalinaServer = false;
    private String currentCatalinaDomainName = null;
    private String currentCatalinaServiceName = null;
    private String currentCatalinaEngineName = null;
    private String currentCatalinaDefaultHostName = null;
    private boolean jettyServer = false;

    // J2EE Management information (used in construction of JSR77 ObjectNames)
    // These names correspond to the server being currently managed
    private ObjectName currentDomain = null;
    private ObjectName currentJonasServer = null;
    //the current jonas node server selected from the treecontrol
    //this var is used for when plotting current server graphs.
    //its creation is due to ambiguous meaning of currentJonasServerName
    /**
     * @uml.property  name="currentClusterDaemon"
     */
    private ObjectName currentClusterDaemon = null;
    //before adding a server to a clusterd supervivion, the server to be added should be configured
    //to set infos that are neede by this operation
    //this var is the name of the server to be configured.
    private String currentSrvToConfigure = null;

    /**
     * @uml.property  name="currentDomainName"
     */
    private String currentDomainName = null;
    private String currentJonasServerName = null;
    //the current cluster daemon name
    /**
     * @uml.property  name="currentClusterDaemonName"
     */
    private String currentClusterDaemonName = null;

    // The server hosting JonasAdmin application
    private String adminJonasServerName = null;
    // The hosting server's configuration directory
    private String adminJonasServerConfDir = null;
    private boolean theCurrentJonasServer = false;
    /**
     * Type of deployment in progress : JAR, EAR, WAR, RAR, DATASOURCE.
     */
    private int currentJonasDeploymentType = 0;

    /**
     * Hashtable to store cluster daemons attributes.
     * key: clusterd name, value: an attribute
     *
     */
    Hashtable<String, Hashtable<String, Integer>> clusterdGraphAttributes = null;
    /**
     * List of servers that are already configured for cluster daemon affactation
     * that means they have jonasBase, JavaHome...(cf clusterd.xml)
     */
    Hashtable<String, ServerItem> configuredServerForClusterDaemonList = null;
    /**
     * new cmi Mbeanserver
     * TODO: Remove this before integfrating newCmi to jons.
     *
     */
    public MBeanServerConnection newCmiMbeanServerConnection = null;
    /**
     * Removed servers for each clusterd
     * used if user did not choose to save server remove operation in clusted.xml
     */
    Hashtable<String, ArrayList<String>> removedServersPerClusterd = null;

    Hashtable<String, String> variables = new Hashtable();

//	--------------------------------------------------------- Constructor

    public WhereAreYou() {
        try {
            // Get the name of the Jonas Server who is running the application
            JProp oJProp = JProp.getInstance();
            adminJonasServerName = oJProp.getValue(ConfigurationConstants.JONAS_NAME_PROP);
            adminJonasServerConfDir = oJProp.getConfDir();
            currentDomainName = oJProp.getValue(ConfigurationConstants.DOMAIN_NAME_PROP);
            currentDomain = J2eeObjectName.J2EEDomain(currentDomainName);
            currentJonasServerName = adminJonasServerName;
            currentJonasServer = J2eeObjectName.J2EEServer(currentDomainName, currentJonasServerName);
            clusterdGraphAttributes = new Hashtable();
            configuredServerForClusterDaemonList = new Hashtable();
            removedServersPerClusterd = new Hashtable();
        } catch (Exception e) {
            // Current Jonas not found, can't run jonasAdmin
            throw new JonasAdminException(EXCEPTION_JONASSERVER_NOTFOUND, e.getMessage(), e);
        }
    }

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

    /**
     * Initialize the properties in only reading.
     *
     * @param p_Servlet The instance of servlet to access to the parameter of the servlet config
     * @param p_Request The request to access to the HTTP informations
     * @throws JonasAdminException
     */
    public void initialize(final ActionServlet p_Servlet, final HttpServletRequest p_Request)
    throws JonasAdminException {
        // Tags Images Root directory
        String sImagesRoot = p_Servlet.getServletConfig().getInitParameter(
                TAGS_IMAGES_ROOT_KEY);
        if (sImagesRoot != null) {
            sImagesRoot = JonasAdminJmx.replace(sImagesRoot, CONTEXT_MACRO
                    , p_Request.getContextPath());
        }
        this.imagesRoot = sImagesRoot;
        refreshServers(p_Request, currentDomainName, currentJonasServerName);
    }

    /**
     * Return the current Jonas server name.
     *
     * @return The name
     */
    public String getCurrentJonasServerName() {
        return currentJonasServerName;
    }

    /**
     * Return the ObjectName of the MBean associated to the current Jonas server.
     *
     * @return The ObjectName
     */
    public ObjectName getCurrentJonasServer() {
        return currentJonasServer;
    }

    /**
     * Return the current J2EE domain ObjectName.
     *
     * @return The ObjectName
     */
    public ObjectName getCurrentDomain() {
        return currentDomain;
    }

    /**
     * Return the current J2EE domain name.
     *
     * @return The name
     */
    public String getCurrentDomainName() {
        return currentDomainName;
    }

    /**
     * Return the name of the selected node in the tree.
     *
     * @return The name
     */
    public String getSelectedNameNode() {
        if (treeControl != null) {
            TreeControlNode oNode = treeControl.getSelected();
            if (oNode != null) {
                return oNode.getName();
            }
        }
        return null;
    }

    /**
     * Return the URL to refresh the selected node in the tree.
     *
     * @param p_Request HTTP request
     * @param p_Response HTTP response
     * @return The URL
     */
    public String getUrlToRefreshSelectedNode(final HttpServletRequest p_Request
            , final HttpServletResponse p_Response) {
        if (treeControl != null) {
            TreeControlNode oNode = treeControl.getSelected();
            if (oNode != null) {
                // Disable refresh
                treeToRefresh = false;
                // Build URL refresh
                String encodedName = null;
                try {
                    encodedName = java.net.URLEncoder.encode(oNode.getName(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    // Node name can't be encoded
                    encodedName = oNode.getName();
                }
                StringBuffer sb = new StringBuffer();
                sb.append(p_Request.getContextPath());
                sb.append("/");
                sb.append(TREE_PAGE_REFRESH);
                sb.append(encodedName);
                // Force the browser to refresh the tree (Netscape and Mozilla)
                sb.append("&s=");
                sb.append(Math.random());

                return p_Response.encodeURL(sb.toString());
            }
        }
        return null;
    }

    /**
     * Select the node in the tree.
     *
     * @param p_Name The name of node to select
     * @param p_Expand Expand parent branch
     */
    public void selectNameNode(final String p_Name, final boolean p_Expand) {
        if (treeControl != null) {
            // Changing node ?
            if (p_Name.equals(getSelectedNameNode()) == false) {
                // Change node
                treeControl.selectNode(p_Name);
                if (p_Expand == true) {
                    treeControl.expandSelectedParents();
                }
                treeToRefresh = true;
            }
            // Query node not found
            if ((getSelectedTreeControlNode() == null) && (p_Name != null) && (p_Name.length() > 0)) {
                // Try to select the parent node
                String s = p_Name.substring(0, p_Name.lastIndexOf(WhereAreYou.NODE_SEPARATOR));
                if ((s != null) && (s.length() > 0)) {
                    selectNameNode(s, p_Expand);
                }
            }
        }
    }

    /**
     * Return the selected node in the tree.
     *
     * @return The selected node
     */
    public TreeControlNode getSelectedTreeControlNode() {
        if (treeControl != null) {
            return treeControl.getSelected();
        }
        return null;
    }

    /**
     * Return the state of current display of tree.
     *
     * @return True if the current tree is not correctly displaying
     */
    public boolean isTreeToRefresh() {
        return treeToRefresh;
    }

    /**
     * Change the state of current display of tree.
     *
     * @param treeToRefresh True to refresh
     */
    public void setTreeToRefresh(final boolean treeToRefresh) {
        this.treeToRefresh = treeToRefresh;
    }

    /**
     * Refresh all the servers properties.
     *
     * @param p_Request The request to access to the HTTP informations
     * @throws ManagementException if could not connect to the MBeanServer
     * @throws JonasAdminException
     */
    public void refreshServers(final HttpServletRequest p_Request, final String domainName, final String serverName)
    throws ManagementException, JonasAdminException {
        refreshJonas(p_Request, serverName);
        applicationServerPort = p_Request.getServerPort();
        applicationContextPath = p_Request.getContextPath();
        refreshCatalina(p_Request, domainName);
        refreshJetty(p_Request, domainName);
    }
    public void refreshServers(final HttpServletRequest p_Request) {
        // Nothing to do, no server change
    }
    /**
     * Refresh the Catalina server properties.
     *
     * @param p_Request The request to access to the HTTP informations
     */
    public void refreshCatalina(final HttpServletRequest p_Request, final String domainName) {
        resetCatalina();
        try {
            String servletServerName = getServletServerName(domainName);
            if (servletServerName == null) {
                return;
            }
            String sServer = servletServerName.toLowerCase();
            catalinaServer = (sServer.indexOf("tomcat") > -1);
            if (catalinaServer) {
                ObjectName onServer = JonasAdminJmx.getFirstMbean(CatalinaObjectName.catalinaServer(), currentJonasServerName);
                ObjectName[] aonServices = (ObjectName[]) JonasManagementRepr.getAttribute(onServer
                        , "serviceNames", currentJonasServerName);
                // Service : the first !
                currentCatalinaServiceName = aonServices[0].getKeyProperty("serviceName");
                // Domain
                currentCatalinaDomainName = aonServices[0].getDomain();
                // Engine
                currentCatalinaEngineName = currentCatalinaDomainName;
                ObjectName onEngine = CatalinaObjectName.catalinaEngine(currentCatalinaDomainName);
                // Default Host
                currentCatalinaDefaultHostName = (String) JonasManagementRepr.getAttribute(onEngine
                        , "defaultHost", currentJonasServerName);
            }
        } catch (Exception e) {
            // none
        }
    }

    /**
     * Refresh the Jetty server properties.
     *
     * @param p_Request The request to access to the HTTP informations
     */
    public void refreshJetty(final HttpServletRequest p_Request, final String domainName) {
        resetJetty();
        try {
            String servletServerName = getServletServerName(domainName);
            if (servletServerName == null) {
                return;
            }
            String sServer = servletServerName.toLowerCase();
            jettyServer = (sServer.indexOf("jetty") > -1);
            if (jettyServer == true) {
                // none action
            }
        }
        catch (Exception e) {
            // none
        }
    }

    /**
     * Refresh the managed JOnAS server properties.
     *
     * @param p_Request The request to access to the HTTP informations
     * @throws ManagementException if could not connect to the MBeanServer
     * @throws JonasAdminException
     */
    public void refreshJonas(final HttpServletRequest p_Request, final String serverName)
    throws ManagementException, JonasAdminException {
        resetJonas();
        // Set J2EEServer information
        currentJonasServerName = serverName;
        currentJonasServer = J2eeObjectName.J2EEServer(currentDomainName, serverName);

        // Detect if the current managed JOnAS server is the one where the application is running
        theCurrentJonasServer = adminJonasServerName.equals(currentJonasServerName);

    }

    /**
     * Return in a string the contents of the instance for each propertie.
     * Debug utility.
     *
     * @return The string contents
     */
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("imagesRoot=[").append(imagesRoot).append("] ");
        sb.append("treeControl=[").append(treeControl).append("] ");
        sb.append("catalinaServer=[").append(catalinaServer).append("] ");
        return sb.toString();
    }

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

    /**
     * Return the name of the servlet server.
     * @return The name of the servlet server.
     */
    protected String getServletServerName(final String domainName) throws ManagementException {
        String servletServerName = null;
        ObjectName on = JonasObjectName.webContainerService(domainName);
        if (JonasManagementRepr.isRegistered(on, currentJonasServerName)) {
            servletServerName = (String) JonasManagementRepr.getAttribute(on, "ServerName", currentJonasServerName);
        }
        return servletServerName;
    }

    /**
     * Reset the Catalina server properties.
     */
    protected void resetCatalina() {
        catalinaServer = false;
        currentCatalinaServiceName = null;
    }

    /**
     * Reset the Jetty server properties.
     */
    protected void resetJetty() {
        jettyServer = false;
    }

    /**
     * Reset the JOnAS server properties.
     */
    protected void resetJonas() {
        theCurrentJonasServer = false;
        currentJonasServer = null;
        currentJonasServerName = null;
    }

    /**
     * Reset the domain properties.
     */
    protected void resetDomain() {
        currentDomain = null;
        currentDomainName = null;
    }

//	--------------------------------------------------------- Properties Methods

    public String getImagesRoot() {
        return imagesRoot;
    }

    public TreeControl getTreeControl() {
        return treeControl;
    }

    public void setTreeControl(final TreeControl treeControl) {
        this.treeControl = treeControl;
    }

    public boolean isCatalinaServer() {
        return catalinaServer;
    }

    public String getCurrentCatalinaServiceName() {
        return currentCatalinaServiceName;
    }

    public boolean isCurrentJonasServer() {
        return theCurrentJonasServer;
    }

    public int getCurrentJonasDeploymentType() {
        return currentJonasDeploymentType;
    }

    public void setCurrentJonasDeploymentType(final int currentJonasDeploymentType) {
        this.currentJonasDeploymentType = currentJonasDeploymentType;
    }

    public int getApplicationServerPort() {
        return applicationServerPort;
    }

    public String getApplicationContextPath() {
        return applicationContextPath;
    }

    public String getCurrentCatalinaDefaultHostName() {
        return currentCatalinaDefaultHostName;
    }

    public String getCurrentCatalinaEngineName() {
        return currentCatalinaEngineName;
    }

    public String getCurrentCatalinaDomainName() {
        return currentCatalinaDomainName;
    }

    public boolean isJettyServer() {
        return jettyServer;
    }
    /**
     * @return Returns the adminJonasServerName.
     */
     public String getAdminJonasServerName() {
        return adminJonasServerName;
    }

    public String getAdminJonasServerConfDir() {
        return adminJonasServerConfDir;
    }

    /**
     * @return
     * @uml.property  name="currentClusterDaemon"
     */
    public ObjectName getCurrentClusterDaemon() {
        return currentClusterDaemon;
    }

    /**
     * @param currentClusterDaemon
     * @uml.property  name="currentClusterDaemon"
     */
    public void setCurrentClusterDaemon(final ObjectName currentClusterDaemon) {
        this.currentClusterDaemon = currentClusterDaemon;
    }

    /**
     * @return
     * @uml.property  name="currentClusterDaemonName"
     */
    public String getCurrentClusterDaemonName() {
        return currentClusterDaemonName;
    }

    /**
     * @param currentClusterDaemonName
     * @uml.property  name="currentClusterDaemonName"
     */
    public void setCurrentClusterDaemonName(final String currentClusterDaemonName) {
        this.currentClusterDaemonName = currentClusterDaemonName;
    }
    /**
     *
     * @return hashtable containing cluster daemons attributes for graphs
     */
    public Hashtable<String, ?> getClusterdGraphAttributes() {
        return clusterdGraphAttributes;
    }

    public void setClusterdGraphAttributes(
            final Hashtable<String, Hashtable<String, Object>> clusterdGraphAttribute) {
        this.clusterdGraphAttributes = clusterdGraphAttributes;
    }

    /**
     *Get a value of given attribute for given cluster daemon
     * @param clusterd the cluster daemon name
     * @param attKey get value of this attribute
     * @return Value of the given attribute for the given cluster daemon -1 else
     * @throws Exception
     */
    public int getClusterdGraphAttribute(final String clusterd, final String attKey) throws Exception  {
        int ret = -1;
        try {
            Hashtable<String, Integer> myHash = clusterdGraphAttributes.get(clusterd);
            if (myHash != null) {
                ret = myHash.get(attKey);
            }
        } catch (Exception e) {
            throw new Exception("Cannot find value for attribute "+attKey+" from the cluster daemon named  "+clusterd+e);
        }
        return ret;
    }
    /**
     *Set given value of given attribute for given cluster daemon
     * @param clusterd the cluster daemon name
     * @param attKey set value of this attribute
     * @param Val the value to set
     * @throws Exception
     */
    public void setClusterdGraphAttribute(final String clusterd, final String attKey, final Integer val) throws Exception  {
        try {
                Hashtable<String, Integer> myHash = clusterdGraphAttributes.get(clusterd);
                if (myHash != null) {
                    //there is already a valur for this key .
                    myHash.remove(attKey);
                    myHash.put(attKey, val);
                }else {
                    //create the hashtable for the clusterd attributes
                    clusterdGraphAttributes.put(clusterd, new Hashtable<String, Integer>());
                    //and put the given attribute value
                    clusterdGraphAttributes.get(clusterd).put(attKey, val);
                }

        } catch (Exception e) {
            throw new Exception("Cannot put value for attribute "+attKey+"for the cluster daemon named "+clusterd+e);		}

    }

    /**
     * @return the currentSrvToConfigure
     */
    public String getCurrentSrvToConfigure() {
        return currentSrvToConfigure;
    }

    /**
     * @param currentSrvToConfigure the currentSrvToConfigure to set
     */
    public void setCurrentSrvToConfigure(final String currentSrvToConfigure) {
        this.currentSrvToConfigure = currentSrvToConfigure;
    }

    /**
     * The given server has been configuered to be affected to a clusterd.
     * @param srv
     * @throws Exception if the ServerItem parameter is null
     */
    @SuppressWarnings("unchecked")
    public void addSrvConfiguredForClusterd(final ServerItem srv ) throws Exception {
        try {
            if (configuredServerForClusterDaemonList == null) {
                configuredServerForClusterDaemonList = new Hashtable();
            }
            configuredServerForClusterDaemonList.put(srv.getName(), srv);
        } catch (NullPointerException e) {
            // TODO: handle exception
            throw new Exception("Server item must not be null"+e);
        }


    }


    /**
     * Gets a server item for the given key. this server has been configured for clusterd affectation.
     * @param key
     * @return ServerItem corresponding to the given key. null if not found
     * @throws Exception if the ServerItem parameter is null
     *
     */

    @SuppressWarnings({ "unchecked", "finally" })
    public ServerItem getSrvConfiguredForClusterd(final String key ) throws Exception {
        ServerItem ret = null;
        try {
            ret = configuredServerForClusterDaemonList.get(key);
        } catch (NullPointerException e) {
            throw new Exception("Server item name must not be Null "+e);
        }finally {
            return ret;
        }


    }

    /**
     * Checks if the given server is already configured for being affected to a cluster daemon.
     * @param srvName the server to find
     * @return true if the server is already configured for clusterd affectation.
     * @throws Exception
     */
    //TODO Remove this method. getSrvConfiguredForClusterd should return Null if serverItem not found.
    public boolean isConfiguredForClusterd(final String srvName) throws Exception {
        //ret == true : the server is already configured for clusterd affectation
        boolean ret = false;
        try {
           ret = configuredServerForClusterDaemonList.containsKey(srvName);
        } catch (Exception e) {
            throw new Exception("Server name or configuredServerForClusterDaemonList attribute is null "+e);
        }
        return ret;
    }

    /**
     *clears the configuredServerForClusterDaemonList list
     */
    public void clearConfigureForClusterList() {
        if (configuredServerForClusterDaemonList != null) {
            configuredServerForClusterDaemonList.clear();
        }
    }


    /**
     * @param newCmiMbeanServerConnection the newCmiMbeanServerConnection to set
     */
    public void setNewCmiMbeanServerConnection(
            final MBeanServerConnection newCmiMbeanServerConnection) {
        this.newCmiMbeanServerConnection = newCmiMbeanServerConnection;
    }
/**
 * Called when substracting a server to clusterd supervision
 * @param clusterdName the cluster daemon name
 * @param srvName the server to remove
 */
    public void addRemovedServer(final String clusterdName, final String srvName) {
        ArrayList<String> removedServers = removedServersPerClusterd.get(clusterdName);
        if (removedServers == null) {
            removedServers = new ArrayList();
            removedServers.add(srvName);
            removedServersPerClusterd.put(clusterdName, removedServers);
        }else {
            removedServers.add(srvName);
        }
    }
/**
 * Checks if the given server has been removed from clusterd affectation
 * @param clusterdName
 * @param srvName
 * @return
 */

    public boolean isSrvRemovedFromClusterd(final String clusterdName, final String srvName) {
        ArrayList<String> removedServers = removedServersPerClusterd.get(clusterdName);
        if (removedServers != null) {
          return removedServers.contains(srvName);
        }
        return false;
    }

    /**
     * Called when substracting a server to clusterd supervision
     * @param clusterdName the cluster daemon name
     * @param srvName the server to remove
     */
        public void rmvFromClusterdRemovedList(final String clusterdName, final String srvName) {
            ArrayList<String> removedServers = removedServersPerClusterd.get(clusterdName);
            if (removedServers != null) {
                removedServers.remove(srvName);
            }
        }
     /**
     * Add a value for the given key
     * @param key the key to add
     * @param value to add
     */
    public void addVar(final String key, final String value) {
    variables.remove(key);
    variables.put(key, value);
    }

     /**
     * Remove a variable
     * @param key the variable key
     */
    public void removeVar(final String key) {
    variables.remove(key);
    }

    /**
     * Remove a variable
     * @param key the variable key
     */
    public String getVar(final String key) {
    return variables.get(key);
    }


}
