/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2009 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.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts.Globals;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.util.MessageResources;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.jonas.lib.management.extensions.base.JonasManagementRepr;
import org.ow2.jonas.lib.management.extensions.base.mbean.CatalinaObjectName;
import org.ow2.jonas.lib.management.extensions.base.mbean.J2eeMbeanItem;
import org.ow2.jonas.lib.management.extensions.base.mbean.MbeanItem;
import org.ow2.jonas.lib.management.extensions.base.mbean.OwnerMbeanItem;
import org.ow2.jonas.lib.management.extensions.container.ejb.EjbItem;
import org.ow2.jonas.lib.management.extensions.container.ejb.EjbItemByNameComparator;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.lib.util.JonasObjectName;
import org.ow2.jonas.lib.util.JoramObjectName;
import org.ow2.jonas.lib.util.Log;
import org.ow2.jonas.management.extensions.base.api.ManagementException;
import org.ow2.jonas.webapp.jonasadmin.catalina.ConnectorItem;
import org.ow2.jonas.webapp.jonasadmin.catalina.ConnectorItemByPort;
import org.ow2.jonas.webapp.jonasadmin.common.BeanComparator;
import org.ow2.jonas.webapp.jonasadmin.jonasmqconnect.util.MqObjectNames;
import org.ow2.jonas.webapp.jonasadmin.joramplatform.ItemDestination;
import org.ow2.jonas.webapp.jonasadmin.logging.LoggerItem;
import org.ow2.jonas.webapp.jonasadmin.service.container.ContainerItem;
import org.ow2.jonas.webapp.jonasadmin.service.container.ContainerItemByFile;
import org.ow2.jonas.webapp.jonasadmin.service.container.WebAppItem;
import org.ow2.jonas.webapp.jonasadmin.service.container.WebAppItemByPathContext;
import org.ow2.jonas.webapp.jonasadmin.service.resource.ResourceItem;
import org.ow2.jonas.webapp.jonasadmin.service.resource.ResourceItemByFile;
import org.ow2.jonas.webapp.jonasadmin.service.webservice.provider.JOnASProvider;
import org.ow2.jonas.webapp.jonasadmin.service.webservice.provider.element.HandlerItem;
import org.ow2.jonas.webapp.jonasadmin.service.webservice.provider.element.PortComponentItem;
import org.ow2.jonas.webapp.jonasadmin.service.webservice.provider.element.WebServiceDescriptionItem;
import org.ow2.jonas.webapp.taglib.TreeBuilder;
import org.ow2.jonas.webapp.taglib.TreeControl;
import org.ow2.jonas.webapp.taglib.TreeControlNode;
/**
 * Implementation of <code>TreeBuilder</code> that adds the nodes required
 * for administering a JOnAS domain / server.
 *
 * @author Michel-Ange ANTON (initial developer)
 * @author Adriana Danes : add nodes for JMS service
 * @author Florent Benoit (changes for struts 1.2.2)
 * @author eyindanga
 */
public class JonasTreeBuilder implements TreeBuilder {

//  ----------------------------------------------------- Instance Variables
    private static Logger logger = Log.getLogger(Log.JONAS_ADMIN_PREFIX);
//  ---------------------------------------------------- TreeBuilder Methods
    /**
     * Add the required nodes to the specified <code>treeControl</code>
     * instance.
     *
     * @param treeControl The <code>TreeControl</code> to which we should
     *  add our nodes
     * @param servlet The controller servlet for the admin application
     * @param request The servlet request we are processing
     */
    public void buildTree(final TreeControl treeControl, final ActionServlet servlet
            , final HttpServletRequest request) {
        try {
            TreeControlNode baseRootNode = treeControl.getRoot();
            MessageResources resources = (MessageResources) servlet.getServletContext().
            getAttribute(Globals.MESSAGES_KEY);
            // TODO Flex integration
            //getDomainNode(baseRootNode, resources, request);
            getRootNode(baseRootNode, resources, request);
        } catch (Throwable t) {
            t.printStackTrace(System.out);
        }
    }

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

    protected void getRootNode(final TreeControlNode p_BaseRootNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String domainName = oWhere.getCurrentDomainName();
        String adminServerName = oWhere.getAdminJonasServerName();
        boolean master = isMaster(p_Request, domainName, adminServerName);
        String managedServerName = oWhere.getCurrentJonasServerName();
        String sNodeLabel = "JonasAdmin";
        String rootName = "domain";
        String sIcon = "icon/domain_jonas.gif";
        TreeControlNode rootNode = new TreeControlNode(rootName, sIcon, sNodeLabel, null, "content", true);
        if (!addNode(p_BaseRootNode, rootNode)) {
            return;
        }
        // Add children
        if (master) {
            getMonitoring(rootNode, p_Resources, p_Request, domainName, managedServerName);
            getDomainNode(rootNode, p_Resources, p_Request);
            getDomainDeploy(rootNode, p_Resources, p_Request);
        }
        getServer(rootNode, p_Resources, p_Request, domainName, managedServerName);
        getJoramPlatform(rootNode, managedServerName, p_Resources, p_Request);
        getMBeans(rootNode, p_Resources, p_Request);
    }
    /**
     * Append node for the domain management (struts version).
     *
     * @param p_RootNode Root node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getDomainNode(final TreeControlNode p_RootNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        // Add domain node
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        //String sDomain = oWhere.getCurrentDomain().toString();// OBJECT_NAME
        String sDomainName = oWhere.getCurrentDomainName();// value of the 'name' key property
        String sServerName = oWhere.getCurrentJonasServerName();

        String sNodeLabel = p_Resources.getMessage("treenode.jonas.domain") + " ( " + sDomainName + " )";
        // domain*domain
        String sNodeName = p_RootNode.getName() + WhereAreYou.NODE_SEPARATOR + "domain";
        TreeControlNode domainNode = new TreeControlNode(sNodeName
                , "icon/domain_jonas.gif"
                , sNodeLabel
                , "EditDomain.do?select=" + encode(sDomainName) + "&version=jsp"
                , "content", true);
        addNode(p_RootNode, domainNode);
    }

    /**
     * Returns if the current server (with discovery running) is a master server.
     * @return if the current server is a master server.
     */
    protected boolean isMaster(final HttpServletRequest p_Request, final String domainName, final String serverName) {
        boolean result = false;
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        ObjectName oObjectName = oWhere.getCurrentDomain();
        if (JonasAdminJmx.hasMBeanName(oObjectName, serverName)) {
            result = ((Boolean) JonasManagementRepr.getAttribute(oObjectName, "master", serverName)).booleanValue();
        }
        return result;
    }

    /**
     * Append nodes for domain management deployment.
     *
     * @param p_DomainNode Domain node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     * @param p_DomainName The name of the domain.
     */
    protected void getDomainDeploy(final TreeControlNode p_RootNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        String domainName = oWhere.getCurrentDomainName();

        String deployments = p_Resources.getMessage("treenode.jonas.server.deployments");
        String label = p_Resources.getMessage("treenode.jonas.domain") + " " + deployments;
        String nodeName = p_RootNode.getName() + WhereAreYou.NODE_SEPARATOR + deployments;
        TreeControlNode nodeDeployments = new TreeControlNode(nodeName
                , "icon/deployDomainManage.gif"
                , label, null, "content", false);
        if (addNode(p_RootNode, nodeDeployments, 1)) {
            getDomainDeploymentEar(nodeDeployments, p_Resources);
            getDomainDeploymentEjb(nodeDeployments, p_Resources);
            getDomainDeploymentWebAppli(nodeDeployments, p_Resources);
            getDomainDeploymentRar(nodeDeployments, p_Resources);
            getDomainDeployment(nodeDeployments, p_Resources);
        }
    }

    /**
     * Append node for Ear deployment using domain management.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDomainDeploymentEar(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_EAR
                , "icon/deployDomain_ear.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments." + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_EAR)
                , "EditDomainDeploy.do?type=" + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_EAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }


    /**
     * Append node for all deployment using domain management.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDomainDeployment(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DOMAIN_DEPLOYMENT_STRING
                , "icon/deployDomain_ear.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments." + WhereAreYou.DOMAIN_DEPLOYMENT_STRING)
                , "EditDomainDeploy.do?type=" + WhereAreYou.DOMAIN_DEPLOYMENT_STRING
                , "content", false);

        addNode(p_NodeDeployments, oNode);
    }
    /**
     * Append node for Ejb deployment using domain management.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDomainDeploymentEjb(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_JAR
                , "icon/deployDomain_jar.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments." + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_JAR)
                , "EditDomainDeploy.do?type=" + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_JAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append node for Web deployment using domain management.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDomainDeploymentWebAppli(final TreeControlNode p_NodeDeployments
            , final MessageResources p_Resources) {
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_WAR
                , "icon/deployDomain_war.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments." + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_WAR)
                , "EditDomainDeploy.do?type=" + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_WAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append node for Rar deployment using domain management.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDomainDeploymentRar(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_RAR
                , "icon/deployDomain_rar.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments." + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_RAR)
                , "EditDomainDeploy.do?type=" + WhereAreYou.DOMAIN_DEPLOYMENT_STRING_RAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }
    /**
     * Append nodes for monitoring of elements in the domain (servers, clusters, cluster daemons)
     */
    protected void getMonitoring(final TreeControlNode p_DomainNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request, final String domainName, final String serverName) {
        String domainNodeName = p_DomainNode.getName();
        TreeControlNode nodeMonitoring = new TreeControlNode(domainNodeName
                + WhereAreYou.NODE_SEPARATOR + "monitoring"
                , "icon/monitoring.gif"
                , p_Resources.getMessage("treenode.jonas.domain.monitoring")
                , null, "content", true);
        if (addNode(p_DomainNode, nodeMonitoring, 0)) {
            getMonitoringNodeList(nodeMonitoring, p_Resources, p_Request, domainName, serverName);
            getMonitoringClusterList(nodeMonitoring, p_Resources, p_Request, domainName, serverName);
            getMonitoringCDList(nodeMonitoring, p_Resources, p_Request, domainName, serverName, false);
        }
    }
    /**
     * Append nodes for servers monitoring
     */
    protected void getMonitoringNodeList(final TreeControlNode p_ParentNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request, final String domainName, final String serverName) {
        // get server proxies
        try {
            ObjectName on = JonasObjectName.serverProxys(domainName);
            Iterator itNames = JonasAdminJmx.getListMbean(on, serverName).iterator();
            while (itNames.hasNext()) {
                ObjectName elem = (ObjectName) itNames.next();
                TreeControlNode node = new TreeControlNode(p_ParentNode.getName()
                        + WhereAreYou.NODE_SEPARATOR + elem.getKeyProperty("name")
                        , "icon/BalJonasTree.gif"
                        , elem.getKeyProperty("name")
                        , "DisplayNodeInfo.do?node=" + elem.getKeyProperty("name")
                        , "content", true);
                addNode(p_ParentNode, node);
            }
        } catch (MalformedObjectNameException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return;
        }
    }

    /**
     * Append nodes for clusters monitoring
     */
    protected void getMonitoringClusterList(final TreeControlNode p_ParentNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request, final String domainName, final String serverName) {

        String clusterType;
        String iconPath;
        String membersAttribute;
        String clusterActionPage;
        String memberActionPage;

        // tomcat cluster
        clusterType = "TomcatCluster";
        iconPath = "icon/domain_jonas.gif";
        membersAttribute = "Members";
        clusterActionPage = "TomcatClusterInfo.do?clust=";
        memberActionPage = "TomcatMemberInfo.do";

        displayClusterMembers(domainName, p_ParentNode, clusterType,
                iconPath, membersAttribute,
                clusterActionPage, memberActionPage,
                domainName, serverName);


        // loadbalancing cluster
        clusterType = "JkCluster";
        iconPath = "icon/domain_jonas.gif";
        membersAttribute = "Members";
        clusterActionPage = "JkClusterInfo.do?clust=";
        memberActionPage = "JkMemberInfo.do";

        displayClusterMembers(domainName, p_ParentNode, clusterType,
                iconPath, membersAttribute,
                clusterActionPage, memberActionPage,
                domainName, serverName);

        // CMI cluster
        clusterType = "CmiCluster";
        iconPath = "icon/domain_jonas.gif";
        membersAttribute = "Members";
        clusterActionPage = "CmiClusterInfo.do?clust=";
        memberActionPage = "CmiMemberInfo.do";

        displayClusterMembers(domainName, p_ParentNode, clusterType,
                iconPath, membersAttribute,
                clusterActionPage, memberActionPage,
                domainName, serverName);

        // EjbHa cluster
        clusterType = "EjbHaCluster";
        iconPath = "icon/domain_jonas.gif";
        membersAttribute = "Members";
        clusterActionPage = "EjbHaClusterInfo.do?clust=";
        memberActionPage = "EjbHaMemberInfo.do";

        displayClusterMembers(domainName, p_ParentNode, clusterType,
                iconPath, membersAttribute,
                clusterActionPage, memberActionPage,
                domainName, serverName);

        // Joram cluster
        clusterType = "JoramCluster";
        iconPath = "icon/domain_jonas.gif";
        membersAttribute = "Members";
        clusterActionPage = "JoramClusterInfo.do?clust=";
        memberActionPage = "JoramMemberInfo.do";

        displayClusterMembers(domainName, p_ParentNode, clusterType,
                iconPath, membersAttribute,
                clusterActionPage, memberActionPage,
                domainName, serverName);

        // Logical cluster
        clusterType = "LogicalCluster";
        iconPath = "icon/domain_jonas.gif";
        membersAttribute = "Members";
        clusterActionPage = "LogicalClusterInfo.do?clust=";
        memberActionPage = "LogicalMemberInfo.do";

        displayClusterMembers(domainName, p_ParentNode, clusterType,
                iconPath, membersAttribute,
                clusterActionPage, memberActionPage,
                domainName, serverName);
    }
    /**
     *
     * @param sDomainName
     * @param p_ParentNode
     * @param clusterType
     * @param iconPath
     * @param membersAttribute
     * @param clusterActionPage
     * @param memberActionPage
     */
    private void displayClusterMembers(final String sDomainName, final TreeControlNode p_ParentNode, final String clusterType,
            final String iconPath, final String membersAttribute,
            final String clusterActionPage, final String memberActionPage, final String domainName, final String serverName) {
        boolean isLogicalCluster = false;
        if (clusterType.equals("LogicalCluster")) {
            isLogicalCluster = true;
        }
        ObjectName onClusters;
        try {
            onClusters = JonasObjectName.clusters(sDomainName, clusterType);
            Iterator itNames = JonasAdminJmx.getListMbean(onClusters, serverName).iterator();
            while (itNames.hasNext()) {
                ObjectName on = (ObjectName) itNames.next();
                String clusterName = on.getKeyProperty("name");
                if (clusterName.equals(domainName)) {
                    continue;
                }
                String clusterNodeName = clusterName + " - (" + on.getKeyProperty("type") + ")";
                // Cluster node
                TreeControlNode nodeCluster = new TreeControlNode(p_ParentNode.getName()
                        + WhereAreYou.NODE_SEPARATOR + clusterNodeName
                        , iconPath
                        , clusterNodeName
                        , clusterActionPage + clusterName
                        , "content", true);
                if (addNode(p_ParentNode, nodeCluster)) {
                    String[] members = null;
                    members = (String[]) JonasManagementRepr.getAttribute(on, membersAttribute, serverName);
                    String memberAction = null;
                    if (members != null) {
                        for (int i = 0; i < members.length; i++) {
                            ObjectName onMember = new ObjectName(members[i]);
                            String memberName = onMember.getKeyProperty("name");
                            if ("LogicalCluster".equals(clusterType)) {
                                memberAction = null;
                            } else {
                                memberAction = memberActionPage
                                + "?member=" + memberName
                                + "&clust=" + clusterName;
                            }
                            // Members node
                            TreeControlNode node = new TreeControlNode(nodeCluster.getName()
                                    + WhereAreYou.NODE_SEPARATOR + memberName, "icon/BalJonasTree.gif"
                                    , memberName
                                    , memberAction, "content", true);
                            addNode(nodeCluster, node);
                        }
                    }
                }
            }
        } catch (MalformedObjectNameException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return;
        }
    }

    /**
     * Append nodes for cluster daemons.
     * TO DO remove isNotMonitoring usage. This method is now always called
     * for monitoring purpose.
     * @param p_ParentNode
     * @param p_Resources
     * @param p_Request
     * @param domainName
     * @param serverName
     * @param isNotMonitoring
     */
    protected void getMonitoringCDList(final TreeControlNode p_ParentNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request, final String domainName, final String serverName, final boolean isNotMonitoring) {
        try {
            ObjectName on = JonasObjectName.clusterDaemonProxys(domainName);
            Iterator itNames = JonasAdminJmx.getListMbean(on, serverName).iterator();
            while (itNames.hasNext()) {
                ObjectName elem = (ObjectName) itNames.next();
                String state= (String) JonasManagementRepr.getAttribute(elem, "State", serverName);
                if (state.equals("RUNNING")) {
                    TreeControlNode node = new TreeControlNode(p_ParentNode.getName()
                            + WhereAreYou.NODE_SEPARATOR + "ClusterDaemonProxy" + elem.getKeyProperty("name")
                            , "icon/BalJonasGreen.gif"
                            , elem.getKeyProperty("name")
                            , "DaemonProxyClusterInfo.do?node=" + elem.getKeyProperty("name") + "&isNotMonitoring=" + isNotMonitoring
                            , "content", true);
                    addNode(p_ParentNode, node);
                }
            }
        } catch (MalformedObjectNameException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return;
        }
    }

    /**
     * Append nodes for a defined Jonas server.
     *
     * @param p_DomainNode Domain node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getServer(final TreeControlNode p_DomainNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request
            , final String p_DomainName, final String p_ServerName) {
        // Add server node
        String sServerName = p_ServerName;
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String sServer = oWhere.getCurrentJonasServer().toString();
        String sNodeLabel = p_Resources.getMessage("treenode.jonas.server") + " ( " + sServerName + " )";
        String sNodeName = p_DomainNode.getName() + WhereAreYou.NODE_SEPARATOR + sServerName;
        TreeControlNode serverNode = new TreeControlNode(sNodeName
                , "icon/BalJonasTree.gif"
                , sNodeLabel
                , "EditJonasServer.do?select=" + encode(sServer)
                , "content", true);
        if (addNode(p_DomainNode,serverNode)) {
            getServerMonitoring(serverNode, p_Resources);
            getLogging(serverNode, p_Resources, p_Request);
            getProtocols(serverNode, p_Resources, p_Request);
            boolean refreshServices = false;
            getServices(serverNode, p_Resources, p_Request, p_DomainName, sServerName);
            getDeployments(serverNode, p_Resources, p_Request);
            getResources(serverNode, p_Resources, p_Request);
            getSecurity(serverNode, p_Resources, p_Request);
            // Add node for MQ connector support
            getJonasMqConnectorPlatform(serverNode, sServerName, p_Resources, p_Request);
        }
    }

    /**
     * Append nodes for Server Monitoring.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServerMonitoring(final TreeControlNode p_ServerNode, final MessageResources p_Resources) {
        // Monitoring server Service node
        TreeControlNode node = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "monitoring"
                , "icon/monitoring.gif"
                , p_Resources.getMessage("treenode.jonas.server.monitoring")
                , "EditMonitoring.do"
                , "content", false);
        addNode(p_ServerNode, node);
    }

    /**
     * Append nodes for Logging.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getLogging(final TreeControlNode p_ServerNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        // Logging server Service node
        TreeControlNode node = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "logging"
                , "icon/loggers.gif"
                , p_Resources.getMessage("treenode.jonas.server.logging")
                , "ListLoggers.do"
                , "content", false);
        addNode(p_ServerNode, node);
        // Add all loggers
        getLoggers(node, p_Resources, p_Request);
    }

    /**
     * Append nodes for each logger.
     *
     * @param p_LoggingNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    public void getLoggers(final TreeControlNode p_LoggingNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        // Get WhereAreYou instance in session
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        // Get list of loggers with Action name
        ArrayList al = null;
        try {
            al = JonasAdminJmx.getLoggers(p_Resources, oWhere, true);
            // Build the node of each logger
            LoggerItem oLog;
            String sIcon = "icon/loggers.gif";
            String rootNodeName = p_LoggingNode.getName();
            String nodeName;
            for (int i = 0; i < al.size(); i++) {
                oLog = (LoggerItem) al.get(i);
                if (LoggerItem.LOGGER_JONAS.equals(oLog.getType())) {
                    sIcon = "icon/logger_jonas.gif";
                    nodeName = rootNodeName +  WhereAreYou.NODE_SEPARATOR + LoggerItem.LOGGER_JONAS;
                } else /*if (LoggerItem.LOGGER_CATALINA_ACCESS.equals(oLog.getType()) == true)*/ {
                    sIcon = "icon/logger_http.gif";
                    nodeName = rootNodeName
                    + WhereAreYou.NODE_SEPARATOR
                    + oLog.getType()
                    + WhereAreYou.NODE_SEPARATOR
                    + oLog.getContainerName();
                }
                // Add a logger node
                TreeControlNode node = new TreeControlNode(nodeName, sIcon
                        , oLog.getName()
                        , oLog.getForward()
                        , "content", false);
                addNode(p_LoggingNode, node);
            }
        } catch (MalformedObjectNameException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return;
        }
    }

    /**
     * Append node for the services sub-tree
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     * @exception Exception if an exception occurs building the tree
     */
    protected void getServices(final TreeControlNode serverNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request, final String p_DomainName, final String p_ServerName) {
        // Services node
        TreeControlNode servicesNode = new TreeControlNode(serverNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "services"
                , "icon/services.gif"
                , p_Resources.getMessage("treenode.jonas.server.services")
                , "ListServices.do"
                , "content", false);
        if (addNode(serverNode, servicesNode)) {
            getServicesNodes(servicesNode, p_Resources, p_Request, p_DomainName, p_ServerName, false);
        }
    }

    public void getServicesNodes(final TreeControlNode servicesNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request, final String domainName, final String serverName, final boolean refreshServices) {
        
        // Add EAR service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.earService(domainName), serverName)) {
            getServiceApp(servicesNode, p_Resources, domainName, serverName);
        }
        // Add node for EJB2 and EJB3 services
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.ejbService(domainName), serverName)) {
            getServiceEjbContainer(servicesNode, p_Resources, domainName, serverName);
        } else {
            // check for ejb3
            ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
            String[] services = (String[]) JonasManagementRepr.getAttribute(on, "services", serverName);
            for (String service:services) {
                if ("ejb3".equals(service)) {
                    getServiceEjbContainer(servicesNode, p_Resources, domainName, serverName);
                    break;
                }
            }
        }
        // Add resources service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.resourceService(domainName), serverName)) {
            getServiceResourceAdapter(servicesNode, p_Resources, domainName, serverName);
        }
        // Add web service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.webContainerService(domainName), serverName)) {
            getServiceWeb(servicesNode, p_Resources, p_Request, domainName, serverName);
        }
        // Add dbm service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.databaseService(domainName), serverName)) {
            getServiceDatabase(servicesNode, p_Resources, domainName, serverName);
        }
        // Add depmonitor service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.deployableMonitorService(domainName), serverName)) {
            getServiceDepmonitor(servicesNode, p_Resources, domainName, serverName);
        }
        // Add discovery service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.discoveryService(domainName), serverName)) {
            getServiceDiscovery(servicesNode, p_Resources, domainName, serverName);
        }
        // Add mail service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.mailService(domainName), serverName)) {
            getServiceMail(servicesNode, p_Resources, p_Request, domainName, serverName);
        }
        // Add security service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.securityService(domainName), serverName)) {
            getServiceSecurity(servicesNode, p_Resources, domainName, serverName);
        }
        // Add smartclient service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.smartclient(domainName), serverName)) {
            getServiceSmartclient(servicesNode, p_Resources, domainName, serverName);
        }
        // Add jtm service node
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.transactionService(domainName), serverName)) {
            getServiceTransaction(servicesNode, p_Resources, domainName, serverName);
        }
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.workCleaner(domainName), serverName)) {
            getServiceWorkCleaner(servicesNode, p_Resources, domainName, serverName);
        }
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.workManager(domainName), serverName)) {
            getServiceWorkManager(servicesNode, p_Resources, domainName, serverName);
        }
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.versioning(domainName), serverName)) {
            getServiceVersioning(servicesNode, p_Resources, domainName, serverName);
        }
        if (JonasAdminJmx.hasMBeanName(JonasObjectName.wsService(domainName), serverName)) {
            getServiceWebService(servicesNode, p_Resources, p_Request, domainName, serverName);
        }
    }
    /**
     * Append node for Ear service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *
     * @exception Exception if an exception occurs building the tree
     */
    protected void getServiceApp(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "ear", "icon/service_application.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.ear")
                , "ListAppContainers.do?refresh=true"
                , "content", false);
        if (addNode(p_NodeServices, nodeService)) {
            // Add App Containers nodes
            getAppContainers(nodeService, p_Resources, p_DomainName, p_ServerName);
        }
    }

    /**
     * Append node for all App Containers.
     *
     * @param p_NodeParent Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    public void getAppContainers(final TreeControlNode p_NodeParent, final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        String sPath;
        String sFile;
        String sNodeName;
        String sName;
        ArrayList<ContainerItem> al = new ArrayList<ContainerItem>();
        String serverName = p_ServerName;
        // Get Container List
        ObjectName ons = J2eeObjectName.J2EEApplications(p_DomainName, p_ServerName);
        Iterator itNames = JonasManagementRepr.queryNames(ons, serverName).iterator();
        while (itNames.hasNext()) {
            ObjectName it_on = (ObjectName) itNames.next();
            sPath = JonasManagementRepr.getAttribute(it_on, "earUrl", serverName).toString();
            sFile = JonasAdminJmx.extractFilename(sPath);
            sNodeName = p_NodeParent.getName() + WhereAreYou.NODE_SEPARATOR + sFile;
            sName = it_on.getKeyProperty("name");
            if (sFile != null) {
                al.add(new ContainerItem(sFile, sPath, sNodeName, it_on.toString(), sName));
            }
        }
        // Sort list
        Collections.sort(al, new ContainerItemByFile());
        // Build nodes
        ContainerItem oItem;
        for (int i = 0; i < al.size(); i++) {
            oItem = al.get(i);
            TreeControlNode node = new TreeControlNode(oItem.getNodeName()
                    , "icon/ear.gif"
                    , oItem.getFile()
                    , "EditEar.do?select=" + oItem.getObjectName()
                    , "content", false);
            addNode(p_NodeParent, node);
        }
    }

    /**
     * Append node for EJBContainer service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceEjbContainer(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "ejbContainers"
                , "icon/service_ejb.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.ejbContainers")
                , "ListContainers.do?refresh=true"
                , "content", false);
        if (addNode(p_NodeServices, nodeService)) {
            getContainers(nodeService, p_Resources, p_DomainName, p_ServerName);
        }
    }

    /**
     * Append node for all Containers.
     *
     * @param p_NodeParent Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    public void getContainers(final TreeControlNode p_NodeParent
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        String sPath;
        String sFile;
        String sName;
        String sNodeName;
        ObjectName onContainer;
        ArrayList<ContainerItem> al = new ArrayList<ContainerItem>();
        String parentSName = null;

        // Get Container List
        Iterator itNames = JonasManagementRepr.queryNames(J2eeObjectName.getEJBModules(p_DomainName, p_ServerName), p_ServerName).iterator();
        while (itNames.hasNext()) {
            ObjectName it_on = (ObjectName) itNames.next();
            sPath = ((URL) JonasManagementRepr.getAttribute(it_on, "url", p_ServerName)).toExternalForm();
            sFile = JonasAdminJmx.extractFilename(sPath);
            sNodeName = p_NodeParent.getName() + WhereAreYou.NODE_SEPARATOR + sFile;
            sName = it_on.getKeyProperty("name");

            parentSName = it_on.getKeyProperty(WhereAreYou.J2EE_APPLICATION_KEY);
            /**
             * Allow to build nodes for ejbjars with the same name, contained in differents applications.
             * The identifier will be :sNodeName*parentSName/moduleName
             * The label will be : parentSName/moduleName
             */
            if (parentSName != null && !"none".equals(parentSName) && !"null".equals(parentSName)) {
                String moduleName = sNodeName.substring(sNodeName.lastIndexOf(WhereAreYou.NODE_SEPARATOR) + 1 );
                String nodePrefix = sNodeName.substring(0, sNodeName.lastIndexOf(WhereAreYou.NODE_SEPARATOR) + 1);
                sNodeName = nodePrefix.concat(parentSName.concat(WhereAreYou.NODE_NAME_SEPARATOR + moduleName));
                sFile = parentSName.concat(WhereAreYou.NODE_NAME_SEPARATOR + sFile);
            }
            if (sFile != null) {
                al.add(new ContainerItem(sFile, sPath, sNodeName, it_on.toString(), sName));
            }
        }

        // Sort list
        Collections.sort(al, new ContainerItemByFile());
        // Build nodes
        ContainerItem oItem;
        for (int i = 0; i < al.size(); i++) {
            oItem = al.get(i);
            TreeControlNode node = new TreeControlNode(oItem.getNodeName()
                    , "icon/jar.gif"
                    , oItem.getFile()
                    , "EditContainer.do?select=" + oItem.getObjectName()
                    , "content", false);
            if (addNode(p_NodeParent, node)) {
                // Add ejb node
                getEjbs(node, p_Resources, oItem.getPath(), p_DomainName, p_ServerName, oItem.getName());
            }
        }
    }

    /**
     * Append node for all Ejbs for a Container.
     *
     * @param p_NodeParent Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Filename Filename of container
     */
    protected void getEjbs(final TreeControlNode p_NodeParent, final MessageResources p_Resources
            , final String p_Filename, final String p_DomainName, final String p_ServerName, final String p_moduleName) {
        //String sName;
        Iterator itNames;
        ObjectName on;
        ArrayList<EjbItem> al = new ArrayList<EjbItem>();

        on = J2eeObjectName.getEntityBeans(p_DomainName, p_moduleName, p_ServerName);

        itNames = JonasAdminJmx.getListMbean(on, p_ServerName).iterator();
        while (itNames.hasNext()) {
            al.add(new EjbItem((ObjectName) itNames.next(), p_ServerName));
        }
        on = J2eeObjectName.getStatefulSessionBeans(p_DomainName, p_moduleName, p_ServerName);
        itNames = JonasAdminJmx.getListMbean(on, p_ServerName).iterator();
        while (itNames.hasNext()) {
            al.add(new EjbItem((ObjectName) itNames.next(), p_ServerName));
        }
        on = J2eeObjectName.getStatelessSessionBeans(p_DomainName, p_moduleName, p_ServerName);
        itNames = JonasAdminJmx.getListMbean(on, p_ServerName).iterator();
        while (itNames.hasNext()) {
            al.add(new EjbItem((ObjectName) itNames.next(), p_ServerName));
        }
        on = J2eeObjectName.getMessageDrivenBeans(p_DomainName, p_moduleName, p_ServerName);
        itNames = JonasAdminJmx.getListMbean(on, p_ServerName).iterator();
        while (itNames.hasNext()) {
            al.add(new EjbItem((ObjectName) itNames.next(), p_ServerName));
        }

        // Sort by name
        Collections.sort(al, new EjbItemByNameComparator());

        // Add all node Ejb
        String sNodeName;
        String sAction;
        TreeControlNode nodeEjb;
        EjbItem oEjb;
        for (int i = 0; i < al.size(); i++) {
            oEjb = al.get(i);
            sNodeName = p_NodeParent.getName() + WhereAreYou.NODE_SEPARATOR + oEjb.getName();
            sAction = "EditEjb" + oEjb.getTypeString() + ".do?select=" + oEjb.getObjectName();
            // Add node Ejb
            nodeEjb = new TreeControlNode(sNodeName
                    , "icon/bean.gif"
                    , oEjb.getName()
                    , sAction
                    , "content", false);
            addNode(p_NodeParent, nodeEjb);
        }
    }

    /**
     * Append node for Database service for the JOnAS services.
     *
     * @param pNodeServices Services node for the tree control
     * @param pResources The MessageResources for our localized messages
     * @param pDomainName The name of the current management domain
     * @param pServerName The name of the currently managed JOnAS server
     */
    protected void getServiceDatabase(final TreeControlNode pNodeServices
            , final MessageResources pResources, final String pDomainName, final String pServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(pNodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "database"
                , "icon/service_database.gif"
                , pResources.getMessage("treenode.jonas.server.services.database")
                , "ListDatabases.do?refresh=true"
                , "content", false);
        if (addNode(pNodeServices, nodeService)) {
            // Add Datasources nodes
            getDatasources(nodeService, pResources, pDomainName, pServerName);
        }
    }

    /**
     * Append node for all deployed Datasources.
     *
     * @param pNodeParent Server node for the tree control
     * @param pResources The MessageResources for our localized messages
     * @param pDomainName The name of the current management domain
     * @param pServerName The name of the currently managed JOnAS server
     */
    public void getDatasources(final TreeControlNode pNodeParent
            , final MessageResources pResources, final String pDomainName, final String pServerName) {

        ArrayList al = JonasAdminJmx.getDatasourceFilesDeployed(pDomainName, pServerName);
        // Build nodes
        for (int i = 0; i < al.size(); i++) {
            TreeControlNode node = new TreeControlNode(pNodeParent.getName()
                    + WhereAreYou.NODE_SEPARATOR + al.get(i).toString()
                    , "icon/Datasource.gif"
                    , al.get(i).toString()
                    , "EditDatasource.do?name=" + al.get(i), "content", false);
            addNode(pNodeParent, node);
        }
    }

    /**
     * Append node for Web service for the JOnAS services.
     *
     * @param pNodeServices Services node for the tree control
     * @param pResources The MessageResources for our localized messages
     * @param pRequest The servlet request we are processing
     * @param pDomainName The name of the current management domain
     * @param pServerName The name of the currently managed JOnAS server
     */
    protected void getServiceWeb(final TreeControlNode pNodeServices, final MessageResources pResources
            , final HttpServletRequest pRequest, final String pDomainName, final String pServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(pNodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "web"
                , "icon/service_web.gif"
                , pResources.getMessage("treenode.jonas.server.services.web")
                , "ListWebContainers.do?refresh=true"
                , "content", false);
        if (addNode(pNodeServices, nodeService)) {
            // Add Web Containers nodes
            getWebContainers(nodeService, pResources, pRequest);
        }
    }

    /**
     * Append node for all Web Containers.
     *
     * @param p_NodeParent Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    public void getWebContainers(final TreeControlNode p_NodeParent, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        String domainName = oWhere.getCurrentDomainName();
        ArrayList<WebAppItem> al = new ArrayList<WebAppItem>();
        // Detect Catalina items present
        if (oWhere.isCatalinaServer()) {
            // Get the list of WebModule
            Iterator itOns = JonasAdminJmx.getListMbean(J2eeObjectName.getWebModules(oWhere.
                    getCurrentCatalinaDomainName()), serverName).iterator();
            while (itOns.hasNext()) {
                WebAppItem item = new WebAppItem((ObjectName) itOns.next(), oWhere.getCurrentCatalinaDefaultHostName());
                al.add(item);
            }
        }
        // Detect Jetty items present
        else if (oWhere.isJettyServer()) {
            ObjectName on;
            String sPathContext;
            HashMap<String, WebAppItem> hWebAppItems = new HashMap<String, WebAppItem>();

            // Get the list of Jetty contexts
            Iterator itOnContexts = JonasAdminJmx.getListMbean(JettyObjectName.jettyContexts(domainName), serverName).
            iterator();
            while (itOnContexts.hasNext()) {
                on = (ObjectName) itOnContexts.next();
                sPathContext = on.getKeyProperty("context");
                if (sPathContext != null) {
                    if (!hWebAppItems.containsKey(sPathContext) && on.getKeyProperty("WebApplicationContext") != null &&
                            on.getKeyProperty("WebApplicationHandler") == null && on.getKeyProperty("config") == null) {
                        WebAppItem item = new WebAppItem(sPathContext, on.toString());
                        hWebAppItems.put(sPathContext, item);
                    }
                }
            }
            // Prepare to display
            al.addAll(hWebAppItems.values());
        }
        WebAppItemByPathContext webAppItemByPathContext = new WebAppItemByPathContext();
        // Sort list
        Collections.sort(al, webAppItemByPathContext);
        // Build nodes
        WebAppItem oItem;
        for (int i = 0; i < al.size(); i++) {
            oItem = al.get(i);
            TreeControlNode node = new TreeControlNode(p_NodeParent.getName()
                    + WhereAreYou.NODE_SEPARATOR + oItem.getObjectName()
                    , "icon/war.gif"
                    , oItem.getLabelPathContext()
                    , "EditWebApp.do?on=" + oItem.getObjectName()
                    , "content", false);
            addNode(p_NodeParent, node);
        }
    }

    /**
     * Append node for Transaction service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     *
     * @exception Exception if an exception occurs building the tree
     */
    protected void getServiceTransaction(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "transaction"
                , "icon/service_transaction.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.transaction")
                , "EditJtmService.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }

    /**
     * Append node for discovery service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceDiscovery(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "discovery"
                , "icon/service_discovery.png"
                , p_Resources.getMessage("treenode.jonas.server.services.discovery")
                , "EditServiceDiscovery.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }

    /**
     * Append node for depmonitor service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceDepmonitor(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "depmonitor"
                , "icon/deploy_ear.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.depmonitor")
                , "EditServiceDepmonitor.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }
    /**
     * Append node for work manager service (wm) for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceWorkManager(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "workmanager"
                , "icon/service_workmanager.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.workmanager")
                , "EditWorkmanagerService.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }

    /**
     * Append node for work cleaner service (wc) for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceWorkCleaner(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "workcleaner"
                , "icon/service_workcleaner.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.workcleaner")
                , "EditWorkcleanerService.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }
    /**
     * Append node for versioning service into the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceVersioning(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "versioning"
                , "icon/service_versioning.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.versioning")
                , "EditVersioningService.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }
    /**
     * Append node for smartclient service into the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceSmartclient(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "smartclient"
                , "icon/service_smartclient.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.smartclient")
                , "EditSmartclientService.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }
    /**
     * Append node for WebService (ws) service for the JOnAS services.
     *
     * @param p_NodeServices
     *            Services node for the tree control
     * @param p_Resources
     *            The MessageResources for our localized messages
     * @param request
     *            The HTTP request object currently in use.
     * @param p_DomainName
     *            The domain name for the instance
     * @param p_ServerName
     *            The server name for the instance being monitored
     */
    public void getServiceWebService(final TreeControlNode p_NodeServices,
            final MessageResources p_Resources, final HttpServletRequest request, final String p_DomainName,
            final String p_ServerName) {
        String nodeName = p_NodeServices.getName() + WhereAreYou.NODE_SEPARATOR + "WebService";
        TreeControlNode nodeService = null;
        // Rebuild the webservice tree.
        nodeService = p_NodeServices.getTree().findNode(nodeName);
        if (nodeService != null) {
            nodeService.remove();
        }
        // (Re)Add Web Service node
        nodeService = new TreeControlNode(
                nodeName,
                "icon/war.gif",
                p_Resources.getMessage("treenode.jonas.server.services.webservices"),
                "ListWebService.do",
                "content",
                false);
        if (addNode(p_NodeServices, nodeService)) {
            getWebServiceDetails(nodeService, p_Resources, request);
        }
    }

    /**
     * Append Web Service names for web services node in tree.
     *
     * @param p_WebServicesNode
     *            Web Services node for the tree control
     * @param p_Resources
     *            The MessageResources for our localized messages
     * @param p_Request
     *            The servlet request we are processing
     */
    public void getWebServiceDetails(final TreeControlNode p_webServicesNode,
            final MessageResources p_Resources, final HttpServletRequest p_Request) {
        // Get WhereAreYou
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(
                WhereAreYou.SESSION_NAME);

        // Get the server name
        String serverName = oWhere.getCurrentJonasServerName();
        // Get the list of webservice descriptions from mbean server.
        Collection al = new ArrayList();
        JOnASProvider jProvider = new JOnASProvider(serverName);
        try {
            al = jProvider.getWebServiceDescription();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return;
        }

        // Build the nodes
        TreeControlNode node;
        WebServiceDescriptionItem oWebServiceDescription = null;
        String sLabel;
        Iterator it = al.iterator();
        while (it.hasNext()) {
            oWebServiceDescription = (WebServiceDescriptionItem) it.next();
            node = new TreeControlNode(p_webServicesNode.getName()
                    + WhereAreYou.NODE_SEPARATOR
                    + oWebServiceDescription.getName()
                    , "icon/war.gif"
                    , oWebServiceDescription.getName()
                    , "WebServiceDetails.do?select=" + oWebServiceDescription.getName()
                    , "content", false);
            if (addNode(p_webServicesNode, node)) {
                getPortComponents(oWebServiceDescription, node, p_Resources);
            }
        }
    }

    /**
     * Append port component names for a web service node in tree.
     *
     * @param wsd
     *            Web Service Description for current web service.
     * @param p_WebServicesNode
     *            Connector node for the tree control
     * @param p_Resources
     *            The MessageResources for our localized messages
     */
    private void getPortComponents(final WebServiceDescriptionItem wsd,
            final TreeControlNode p_webServiceNode, final MessageResources p_Resources) {
        String sLabel;
        // Build the nodes
        TreeControlNode node = null;
        for (int i = 0; i < wsd.getPortComponentCount(); i++) {
            PortComponentItem pc = wsd.getPortComponent(i);
            node = new TreeControlNode(p_webServiceNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + pc.getName()
                    , "icon/war.gif"
                    , pc.getName()
                    , "PortComponentsDetails.do?pcselect=" + pc.getName() + "&wsdselect=" + wsd.getName()
                    , "content", false);
            if (addNode(p_webServiceNode, node)) {
                getPortComponentHandler(wsd, pc, node, p_Resources);
            }
        }

    }

    /**
     * Append handler names for port component node in tree.
     *
     * @param wsd
     *            Web Service Description for current web service.
     * @param pc
     *            Port Component for current web service.
     * @param p_portComponentNode
     *            Port component node for the tree control
     * @param p_Resources
     *            The MessageResources for our localized messages
     */
    private void getPortComponentHandler(final WebServiceDescriptionItem wsd,
            final PortComponentItem pc, final TreeControlNode p_portComponentNode,
            final MessageResources p_Resources) {
        // Build the nodes
        TreeControlNode node = null;
        for (int i = 0; i < pc.getHandlerCount(); i++) {
            HandlerItem handler = pc.getHandler(i);
            node = new TreeControlNode(p_portComponentNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + handler.getName()
                    , "icon/war.gif"
                    , handler.getName()
                    , "HandlersDetails.do?pcselect=" + pc.getName() + "&wsdselect="
                    + wsd.getName() + "&handlerselect=" + handler.getName()
                    , "content", false);
            addNode(p_portComponentNode, node);
        }

    }

    /**
     * Append node for Mail service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceMail(final TreeControlNode p_NodeServices, final MessageResources p_Resources
            , final HttpServletRequest p_Request, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "mail", "icon/service_mail.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.mail")
                , "EditMailService.do"
                , "content", false);
        if (addNode(p_NodeServices, nodeService)) {
            // Add nodes for MailFactories
            getAllSessionMailFactories(nodeService, p_Resources, p_Request);
            getAllMimePartDSMailFactories(nodeService, p_Resources, p_Request);
        }
    }

    public void getAllSessionMailFactories(final TreeControlNode p_NodeParent
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        // Add parent node for all the Session Mail Factories
        TreeControlNode nodeSessionMailFactories = new TreeControlNode(p_NodeParent.getName()
                + WhereAreYou.NODE_SEPARATOR + "session"
                , "icon/mail_session.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.mail.session")
                , "ListSessionMailFactories.do"
                , "content", false);
        if (addNode(p_NodeParent, nodeSessionMailFactories)) {
            // Add a node for each Session Mail Factory
            getSessionMailFactories(nodeSessionMailFactories, p_Resources, p_Request);
        }
    }

    public void getAllMimePartDSMailFactories(final TreeControlNode p_NodeParent
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        // Add parent node for all the Session Mail Factories
        TreeControlNode nodeMimePartMailFactories = new TreeControlNode(p_NodeParent.getName()
                + WhereAreYou.NODE_SEPARATOR + "mimepart"
                , "icon/mail_mime.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.mail.mimepart")
                , "ListMimePartMailFactories.do"
                , "content", false);
        if (addNode(p_NodeParent, nodeMimePartMailFactories)) {
            // Add a node for each Session Mail Factory
            getMimePartMailFactories(nodeMimePartMailFactories, p_Resources, p_Request);
        }
    }

    protected void getSessionMailFactories(final TreeControlNode p_NodeParent
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        String sPath;
        String sFile;
        String sNodeName;
        ArrayList<String> al = new ArrayList<String>();

        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);

        // Get list
        java.util.List deployedFactories = JonasAdminJmx.
        getSessionMailFactoriesDeployed(oWhere);
        Iterator itNames = deployedFactories.iterator();
        while (itNames.hasNext()) {
            al.add(itNames.next().toString());
        }
        // Sort list
        Collections.sort(al);
        // Build nodes
        for (int i = 0; i < al.size(); i++) {
            TreeControlNode node = new TreeControlNode(p_NodeParent.getName()
                    + WhereAreYou.NODE_SEPARATOR + al.get(i).toString()
                    , "icon/mail_session.gif"
                    , al.get(i).toString()
                    , "EditSessionMailFactory.do?name=" + al.get(i).toString()
                    , "content", false);
            addNode(p_NodeParent, node);
        }
    }

    protected void getMimePartMailFactories(final TreeControlNode p_NodeParent
            , final MessageResources p_Resource, final HttpServletRequest p_Request) {
        String sPath;
        String sFile;
        String sNodeName;
        ArrayList<String> al = new ArrayList<String>();

        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);

        // Get List
        Iterator itNames = ((java.util.List) JonasAdminJmx.getMimeMailPartFactoriesDeployed(oWhere)).
        iterator();
        while (itNames.hasNext()) {
            al.add(itNames.next().toString());
        }
        // Sort list
        Collections.sort(al);
        // Build nodes
        for (int i = 0; i < al.size(); i++) {
            TreeControlNode node = new TreeControlNode(p_NodeParent.getName()
                    + WhereAreYou.NODE_SEPARATOR + al.get(i).toString()
                    , "icon/mail_mime.gif"
                    , al.get(i).toString()
                    , "EditMimePartMailFactory.do?name=" + al.get(i).toString()
                    , "content", false);
            addNode(p_NodeParent, node);
        }
    }

    /**
     * Append node for Resource service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getServiceResourceAdapter(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "resourceAdapter"
                , "icon/service_resource.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.resource")
                , "ListResourceAdapters.do?refresh=true"
                , "content", false);
        if (addNode(p_NodeServices, nodeService)) {
            // Add Containers nodes
            getResourceAdapters(nodeService, p_Resources, p_DomainName, p_ServerName);
        }
    }

    /**
     * Append node for all Resource Adapters.
     *
     * @param p_NodeParent Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param pDomainName The name of the current management domain
     * @param pServerName The name of the currently managed JOnAS server
     */
    public void getResourceAdapters(final TreeControlNode p_NodeParent, final MessageResources p_Resources,
            final String p_DomainName, final String p_ServerName) {
        String sPath;
        String sFile;
        String sNodeName;
        String sName;
        ObjectName on;
        ArrayList<ResourceItem> al = new ArrayList<ResourceItem>();

        // Get Resource Adapters
        ObjectName ons = J2eeObjectName.getResourceAdapters(p_DomainName, p_ServerName);
        Iterator itNames = JonasManagementRepr.queryNames(ons, p_ServerName).iterator();
        while (itNames.hasNext()) {
            ObjectName it_on = (ObjectName) itNames.next();
            sPath = (String) JonasManagementRepr.getAttribute(it_on, "fileName", p_ServerName);
            sFile = JonasAdminJmx.extractFilename(sPath);
            sNodeName = p_NodeParent.getName() + WhereAreYou.NODE_SEPARATOR + sFile;
            sName = it_on.getKeyProperty("name");
            if (sFile != null) {
                al.add(new ResourceItem(sFile, sPath, sNodeName, it_on.toString(), sName));
            }
        }
        // Sort list
        Collections.sort(al, new ResourceItemByFile());
        // Build nodes
        ResourceItem oItem;
        for (int i = 0; i < al.size(); i++) {
            oItem = al.get(i);
            TreeControlNode node = new TreeControlNode(oItem.getNodeName()
                    , "icon/ear.gif"
                    , oItem.getFile()
                    , "EditResourceAdapter.do?select=" + oItem.getObjectName()
                    , "content", false);
            addNode(p_NodeParent, node);
        }
    }

    /**
     * Append node for Security service for the JOnAS services.
     *
     * @param p_NodeServices Services node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *  messages
     */
    protected void getServiceSecurity(final TreeControlNode p_NodeServices
            , final MessageResources p_Resources, final String p_DomainName, final String p_ServerName) {
        // Add Service node
        TreeControlNode nodeService = new TreeControlNode(p_NodeServices.getName()
                + WhereAreYou.NODE_SEPARATOR + "security"
                , "icon/service_security.gif"
                , p_Resources.getMessage("treenode.jonas.server.services.security")
                , "EditServiceSecurity.do"
                , "content", false);
        addNode(p_NodeServices, nodeService);
    }

    /**
     * Append nodes for Deployments services for the specified server.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDeployments(final TreeControlNode p_ServerNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        // Deployments node
        TreeControlNode nodeDeployments = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "deployments", "icon/deploy.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments"), null, "content", true);
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        String domainName = oWhere.getCurrentDomainName();

        if (addNode(p_ServerNode, nodeDeployments)) {
            // Detail Service node
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.earService(domainName), serverName)) {
                getDeploymentEar(nodeDeployments, p_Resources);
            }
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.ejbService(domainName), serverName)) {
                getDeploymentEjb(nodeDeployments, p_Resources);
            } else {
                // check for ejb3
                ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
                String[] services = (String[]) JonasManagementRepr.getAttribute(on, "services", serverName);
                for (String service:services) {
                    if ("ejb3".equals(service)) {
                        getDeploymentEjb(nodeDeployments, p_Resources);
                        break;
                    }
                }
            }
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.webContainerService(domainName), serverName)) {
                getDeploymentWebAppli(nodeDeployments, p_Resources);
            }
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.resourceService(domainName), serverName)) {
                getDeploymentRar(nodeDeployments, p_Resources);
            }
            getDeployment(nodeDeployments, p_Resources);
        }
    }
    /**
     * Append node for deployment.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDeployment(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        // Add node
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DEPLOYMENT_STRING
                , "icon/deploy_ear.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments."
                        + WhereAreYou.DEPLOYMENT_STRING)
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append node for Ear deployment.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDeploymentEar(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        // Add node
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DEPLOYMENT_STRING_EAR
                , "icon/deploy_ear.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments."
                        + WhereAreYou.DEPLOYMENT_STRING_EAR)
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING_EAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append node for Ejb deployment.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDeploymentEjb(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        // Add node
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DEPLOYMENT_STRING_JAR
                , "icon/deploy_jar.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments."
                        + WhereAreYou.DEPLOYMENT_STRING_JAR)
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING_JAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append node for Web deployment.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getDeploymentWebAppli(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        // Add node
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DEPLOYMENT_STRING_WAR
                , "icon/deploy_war.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments."
                        + WhereAreYou.DEPLOYMENT_STRING_WAR)
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING_WAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append node for Rar deployment.
     *
     * @param p_NodeDeployments Deployment node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     *
     * @exception Exception if an exception occurs building the tree
     */
    protected void getDeploymentRar(final TreeControlNode p_NodeDeployments, final MessageResources p_Resources) {
        // Add node
        TreeControlNode oNode = new TreeControlNode(p_NodeDeployments.getName()
                + WhereAreYou.NODE_SEPARATOR + WhereAreYou.DEPLOYMENT_STRING_RAR
                , "icon/deploy_rar.gif"
                , p_Resources.getMessage("treenode.jonas.server.deployments."
                        + WhereAreYou.DEPLOYMENT_STRING_RAR)
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING_RAR
                , "content", false);
        addNode(p_NodeDeployments, oNode);
    }

    /**
     * Append nodes for Resources services for the specified server.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getResources(final TreeControlNode p_ServerNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        String domainName = oWhere.getCurrentDomainName();

        // Resources node
        TreeControlNode nodeDeployments = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "resources"
                , "icon/resources.gif"
                , p_Resources.getMessage("treenode.jonas.server.resources")
                , null, "content", false);
        if (addNode(p_ServerNode, nodeDeployments)) {
            // - database resources
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.databaseService(domainName), serverName)) {
                getResourceDatabase(nodeDeployments, p_Resources);
            }
            // - jms resources
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.jmsService(domainName), serverName)) {
                getJmsResource(nodeDeployments, p_Resources);
            }
            // - mail resources
            if (JonasAdminJmx.hasMBeanName(JonasObjectName.mailService(domainName), serverName)) {
                getMailResource(nodeDeployments, p_Resources);
            }
        }
    }

    /**
     * Append nodes for Mail Resources for the specified server.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getMailResource(final TreeControlNode p_ServerNode, final MessageResources p_Resources) {
        // Mail resources node
        TreeControlNode nodeDeployments = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "mail"
                , "icon/mail.gif"
                , p_Resources.getMessage("treenode.jonas.server.resources.mail")
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING_MAILFACTORY
                , "content", false);
        addNode(p_ServerNode, nodeDeployments);
    }

    /**
     * Append nodes for Jms Resource for the specified server.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getJmsResource(final TreeControlNode p_ServerNode, final MessageResources p_Resources) {
        // Jms resources node
        TreeControlNode nodeDeployments = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "jms"
                , "icon/jms.gif"
                , p_Resources.getMessage("treenode.jonas.server.resources.jms")
                , "ListJmsResources.do"
                , "content", false);
        addNode(p_ServerNode, nodeDeployments);
    }

    /**
     * Append nodes for Database Resource for the specified server.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    protected void getResourceDatabase(final TreeControlNode p_ServerNode, final MessageResources p_Resources) {
        // Database Resources node
        TreeControlNode nodeDeployments = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "database"
                , "icon/Database.gif"
                , p_Resources.getMessage("treenode.jonas.server.resources.database")
                , "EditDeploy.do?type=" + WhereAreYou.DEPLOYMENT_STRING_DATASOURCE
                , "content", false);
        addNode(p_ServerNode, nodeDeployments);
    }

    /**
     * Append nodes for Security for the specified server.
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getSecurity(final TreeControlNode p_ServerNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {

        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        String domainName = oWhere.getCurrentDomainName();
        // Detect JOnAS item presents
        boolean bJonasSecurityService = JonasAdminJmx.hasMBeanName(JonasObjectName.securityService(domainName), serverName);
        // Detect Catalina items present
        boolean bCatalinaRealm = false;
        if (oWhere.isCatalinaServer()) {
            ObjectName catalinaRealmOn = null;
            try {
                catalinaRealmOn = CatalinaObjectName.catalinaRealm(oWhere.getCurrentCatalinaServiceName());
            } catch (MalformedObjectNameException e) {
                if (logger.isLoggable(BasicLevel.INFO)) {
                    logger.log(BasicLevel.INFO, "Can't get catalina realm: " + e);
                }
                return;
            }
            bCatalinaRealm = JonasAdminJmx.hasMBeanName(catalinaRealmOn, serverName);
        }
        // Add nodes
        if ((bJonasSecurityService) || (bCatalinaRealm)) {
            // Active action
            String sAction = null;
            if (bJonasSecurityService) {
                sAction = "ListRealms.do?realm=all";
            }
            else if (bCatalinaRealm) {
                sAction = "EditSecurityCatalinaRealm.do";
            }
            // Security node
            TreeControlNode nodeSecurity = new TreeControlNode(p_ServerNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + "security"
                    , "icon/security.gif"
                    , p_Resources.getMessage("treenode.jonas.server.security")
                    , sAction
                    , "content", false);
            if (addNode(p_ServerNode, nodeSecurity)) {
                // Detail Security node for JOnAS service
                if (bJonasSecurityService) {
                    getSecurityFactories(nodeSecurity, p_Resources, p_Request);
                }
            }
        }
    }

    /**
     * Append nodes for Security factories for the specified server.
     *
     * @param p_SecurityNode Security node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     */
    public void getSecurityFactories(final TreeControlNode p_SecurityNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        ArrayList al = null;
        String sName = null;
        TreeControlNode nodeSecurityFactories = null;
        TreeControlNode nodeSecurityFactory = null;
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        String domainName = oWhere.getCurrentDomainName();
        // Security Memory factories
        try {
            al = JonasAdminJmx.getSecurityMemoryFactories(domainName, serverName);
        } catch (MalformedObjectNameException e) {
            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get memory security factories: " + e);
            }
        }
        if (al.size() > 0) {
            // Security factories node
            nodeSecurityFactories = new TreeControlNode(p_SecurityNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + "factory.memory"
                    , "icon/security_memory.gif"
                    , p_Resources.getMessage("treenode.jonas.server.security.factory.memory")
                    , "ListRealms.do?realm=memory"
                    , "content", false);
            if (addNode(p_SecurityNode, nodeSecurityFactories)) {
                // List Security factories
                for (int i = 0; i < al.size(); i++) {
                    sName = al.get(i).toString();
                    // Security factory node
                    nodeSecurityFactory = new TreeControlNode(nodeSecurityFactories.getName()
                            + WhereAreYou.NODE_SEPARATOR + sName
                            , "icon/security_memory.gif", sName
                            , "EditMemoryRealm.do?resource=" + sName
                            , "content", false);
                    addNode(nodeSecurityFactories, nodeSecurityFactory);
                }
            }
        }
        // Security Datasource factories
        try {
            al = JonasAdminJmx.getSecurityDatasourceFactories(domainName, serverName);
        } catch (MalformedObjectNameException e) {
            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get datasource security factories: " + e);
            }
        }
        if (al.size() > 0) {
            // Security factories node
            nodeSecurityFactories = new TreeControlNode(p_SecurityNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + "factory.datasource", "icon/security_database.gif"
                    , p_Resources.getMessage("treenode.jonas.server.security.factory.datasource")
                    , "ListRealms.do?realm=datasource", "content", false);
            if (addNode(p_SecurityNode, nodeSecurityFactories)) {
                // List Security factories
                for (int i = 0; i < al.size(); i++) {
                    sName = al.get(i).toString();
                    // Security factory node
                    nodeSecurityFactory = new TreeControlNode(nodeSecurityFactories.getName()
                            + WhereAreYou.NODE_SEPARATOR + sName
                            , "icon/security_database.gif", sName
                            , "EditDatasourceRealm.do?resource=" + sName
                            , "content", false);
                    addNode(nodeSecurityFactories, nodeSecurityFactory);
                }
            }
        }
        // Security Ldap factories
        try {
            al = JonasAdminJmx.getSecurityLdapFactories(domainName, serverName);
        } catch (MalformedObjectNameException e) {
            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get ldap security factories: " + e);
            }
        }
        if (al.size() > 0) {
            // Security factories node
            nodeSecurityFactories = new TreeControlNode(p_SecurityNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + "factory.ldap"
                    , "icon/security_ldap.gif"
                    , p_Resources.getMessage("treenode.jonas.server.security.factory.ldap")
                    , "ListRealms.do?realm=ldap"
                    , "content", false);
            if (addNode(p_SecurityNode, nodeSecurityFactories)) {
                // List Security factories
                for (int i = 0; i < al.size(); i++) {
                    sName = al.get(i).toString();
                    // Security factory node
                    nodeSecurityFactory = new TreeControlNode(nodeSecurityFactories.getName()
                            + WhereAreYou.NODE_SEPARATOR + sName
                            , "icon/security_ldap.gif", sName
                            , "EditLdapRealm.do?resource=" + sName
                            , "content", false);
                    addNode(nodeSecurityFactories, nodeSecurityFactory);
                }
            }
        }
    }

    /**
     * Append nodes for Memory Security Factory for the specified server.
     *
     * @param p_SecurityMemoryNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_ResourceFactory The name of resource
     */
    protected void getSecurityMemoryFactory(final TreeControlNode p_SecurityMemoryNode
            , final MessageResources p_Resources, final String p_ResourceFactory) {
        TreeControlNode node = null;
        // Users node
        node = new TreeControlNode(p_SecurityMemoryNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "users", "icon/security_memory.gif"
                , p_Resources.getMessage("treenode.jonas.server.security.factory.memory.users")
                , "EditMemoryRealmUsers.do?resource=" + p_ResourceFactory
                , "content", false);
        addNode(p_SecurityMemoryNode, node);
        // Groups node
        node = new TreeControlNode(p_SecurityMemoryNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "groups", "icon/security_memory.gif"
                , p_Resources.getMessage("treenode.jonas.server.security.factory.memory.groups")
                , "EditMemoryRealmGroups.do?resource=" + p_ResourceFactory
                , "content", false);
        addNode(p_SecurityMemoryNode, node);
        // Roles node
        node = new TreeControlNode(p_SecurityMemoryNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "roles", "icon/security_memory.gif"
                , p_Resources.getMessage("treenode.jonas.server.security.factory.memory.roles")
                , "EditMemoryRealmRoles.do?resource=" + p_ResourceFactory
                , "content", false);
        addNode(p_SecurityMemoryNode, node);
    }

    /**
     * Append nodes for the Servlet server
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getProtocols(final TreeControlNode p_ServerNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        // Catalina server
        ObjectName cOn;
        try {
            cOn = CatalinaObjectName.catalinaServer();
            if (JonasAdminJmx.hasMBeanName(cOn, serverName)) {
                getCatalinaProtocols(p_ServerNode, p_Resources, p_Request);
            }
        } catch (MalformedObjectNameException e) {
            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get Catalina Server MBean: " + e);
            }
            return;
        }
    }

    /**
     * Append nodes for the Catalina server
     *
     * @param p_ServerNode Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getCatalinaProtocols(final TreeControlNode p_ServerNode, final MessageResources p_Resources
            , final HttpServletRequest p_Request) {
        // Add Catalina server node
        TreeControlNode catalinaNode = new TreeControlNode(p_ServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "protocols"
                , "icon/protocol.gif"
                , p_Resources.getMessage("treenode.jonas.server.protocols")
                , "ListCatalinaConnectors.do"
                , "content", false);
        if (addNode(p_ServerNode, catalinaNode)) {
            // Add Connectors nodes
            getCatalinaConnector(catalinaNode, p_Resources, p_Request);
        }
    }

    /**
     * Append node for the Connector catalina server
     *
     * @param p_CatalinaServerNode Catalina Server node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    protected void getCatalinaConnector(final TreeControlNode p_CatalinaServerNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {
        // Add Connector node
        TreeControlNode connectorNode = new TreeControlNode(p_CatalinaServerNode.getName()
                + WhereAreYou.NODE_SEPARATOR + "connectors"
                , "icon/connectors.gif"
                , p_Resources.getMessage("treenode.jonas.server.protocols.connectors")
                , "ListCatalinaConnectors.do"
                , "content", false);
        if (addNode(p_CatalinaServerNode, connectorNode)) {
            getCatalinaDetailConnectors(connectorNode, p_Resources, p_Request);
        }
    }

    /**
     * Append nodes for all the Connectors catalina server
     *
     * @param p_ConnectorNode Connector node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    public void getCatalinaDetailConnectors(final TreeControlNode p_ConnectorNode
            , final MessageResources p_Resources, final HttpServletRequest p_Request) {

        // Get WhereAreYou
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);

        String serverName = oWhere.getCurrentJonasServerName();
        // Get the domain name
        String sDomain = oWhere.getCurrentCatalinaDomainName();
        int appServerPort = oWhere.getApplicationServerPort();
        // Get the list of connectors
        ArrayList<ConnectorItem> al = new ArrayList<ConnectorItem>();
        ObjectName conns = null;
            try {
                conns = CatalinaObjectName.catalinaConnectors(sDomain);
            } catch (MalformedObjectNameException e) {
                if (logger.isLoggable(BasicLevel.INFO)) {
                    logger.log(BasicLevel.INFO, "Can't get catalina connectors MBeans: " + e);
                }
                return;
            }
            Iterator it = JonasAdminJmx.getListMBeanName(conns, serverName).iterator();
            while (it.hasNext()) {
                String ons = (String) it.next();
                ObjectName connOn = null;
                try {
                    connOn = ObjectName.getInstance(ons);
                } catch (MalformedObjectNameException e) {
                    if (logger.isLoggable(BasicLevel.INFO)) {
                        logger.log(BasicLevel.INFO, "Can't get catalina connector MBean " + ons + ": " + e);
                    }
                    continue;
                }
                ConnectorItem item = new ConnectorItem(connOn, appServerPort, serverName);
                al.add(item);
            }
            // Sort
            Collections.sort(al, new ConnectorItemByPort());
            // Build the nodes
            TreeControlNode node;
            ConnectorItem oConnector;
            String sLabel;
            for (int i = 0; i < al.size(); i++) {
                oConnector = al.get(i);
                String nodeName = p_ConnectorNode.getName()
                + WhereAreYou.NODE_SEPARATOR
                + sDomain
                + WhereAreYou.NODE_SEPARATOR
                + oConnector.getPort();
                String address = oConnector.getAddress();
                if (address != null) {
                    nodeName = nodeName + address;
                }
                node = new TreeControlNode(nodeName, "icon/connector.gif"
                        , oConnector.getLabel()
                        , "EditCatalinaConnector.do?select=" + oConnector.getObjectName()
                        , "content", false);
                addNode(p_ConnectorNode, node);
            }
    }

    /**
     * Append node for JORAM platform management.
     *
     * @param pDomainNode Domain node for the tree control
     * @param jonasServerName the name of the JOnAS server to which the current JORAM server is connected
     * @param pResources  The MessageResources for our localized messages
     * @param p_Request The servlet request we are processing
     */
    public void getJoramPlatform(final TreeControlNode pDomainNode, final String jonasServerName,
            final MessageResources pResources, final HttpServletRequest p_Request) {

        ObjectName joramAdapterOn = null;
        try {
            joramAdapterOn = JoramObjectName.joramAdapter();
        } catch (MalformedObjectNameException e) {
            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get JORAM Adapter MBean: " + e);
            }
            return;
        }

        if (!JonasAdminJmx.hasMBeanName(joramAdapterOn, jonasServerName)) {
            // No Joram to manage
            // reset localServerId in case we just switched management context
            // from a server which has Joram to this server which does not
            if (p_Request.getSession().getAttribute("localId") != null) {
                p_Request.getSession().setAttribute("localId", null);
            }
            return;
        }

        // Joram adapter present, create node for JORAM platform
        TreeControlNode platformNode =
            new TreeControlNode(pDomainNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + "joramplatform"
                    ,"icon/service_jms.gif"
                    ,pResources.getMessage("treenode.joramplatform")
                    ,"EditJoramPlatform.do"
                    ,"content",
                    false);
        // Create node for the local server (Joram server to which the admin client is connected)
        if (addNode(pDomainNode, platformNode)) {
            getJoramServers(platformNode, jonasServerName, joramAdapterOn, pResources, p_Request);
        }
    }

    /**
     * Append nodes for Joram server defined in tbe platform
     * @param platformNode     Joram platform node
     * @param jonasServerName the name of the JOnAS server to which the current JORAM server is connected
     * @param joramAdapterOn  ObjectName of Joram Adapter MBean
     * @param pResources The MessageResources for our localized messages
     * @param p_Request  The servlet request we are processing
     */
    public void getJoramServers(final TreeControlNode platformNode
            , final String jonasServerName
            , final ObjectName joramAdapterOn
            , final MessageResources pResources
            , final HttpServletRequest p_Request) {

        Object attributeValue = null;
        boolean collocatedServer = false;
        attributeValue = JonasManagementRepr.getAttribute(joramAdapterOn, "CollocatedServer", jonasServerName);
        if (attributeValue != null) {
            collocatedServer = ((Boolean) attributeValue).booleanValue();
        }
        // get local Joram server
        String localId = null;
        Short id = null;
        attributeValue = JonasManagementRepr.getAttribute(joramAdapterOn, "ServerId", jonasServerName);
        if (attributeValue != null) {
            id = (Short) attributeValue;
            localId = id.toString();
        }
        // Create the node for the currently managed JORAM server
        TreeControlNode currentServerNode = null;
        String nodeName = null;
        String icon = "icon/service_jms.gif";
        String label = null;
        String action = "EditJoramServer.do?id=" + localId;
        if (collocatedServer) {
            nodeName = platformNode.getName() + WhereAreYou.NODE_SEPARATOR + "joramlocalserver";
            label = pResources.getMessage("treenode.joramplatform.joramlocalserver") + " (" + localId + ")";
        } else {
            nodeName = platformNode.getName() + WhereAreYou.NODE_SEPARATOR + "joramcurrentserver";
            label = pResources.getMessage("treenode.joramplatform.joramcurrentserver") + " (" + localId + ")";
        }
        currentServerNode =  new TreeControlNode(nodeName, icon, label, action, "content", false);
        if (addNode(platformNode, currentServerNode)) {
            // Add local or current server resources
            getJoramResources(currentServerNode, jonasServerName, localId, pResources, p_Request);
        }

        p_Request.getSession().setAttribute("localId", localId);
        p_Request.getSession().setAttribute("collocatedServer", new Boolean(collocatedServer));

        // get the other (remote) Joram servers
        Short[] serversIds = (Short[]) JonasManagementRepr.getAttribute(joramAdapterOn, "ServersIds", jonasServerName);
        if (serversIds != null) {
            String serverId;
            TreeControlNode remoteServerNode = null;
            for (int index = 0; index < serversIds.length; index++) {
                id = serversIds[index];
                serverId = id.toString();
                String joramremoteserver = null;
                if (!id.toString().equals(localId)) {
                    joramremoteserver = "joramremoteserver" + id;
                    nodeName = platformNode.getName() + WhereAreYou.NODE_SEPARATOR + joramremoteserver;
                    label = pResources.getMessage("treenode.joramplatform.joramremoteserver") + " (" + id + ")";
                    action = "EditJoramServer.do?id=" + id;
                    remoteServerNode = new TreeControlNode(nodeName, icon, label, action, "content", false);
                    platformNode.addChild(remoteServerNode);
                    // Add remote server's resources
                    getJoramResources(remoteServerNode, jonasServerName, serverId, pResources, p_Request);
                }
            }
        }
    }
    /**
     * Append nodes for Joram DEstinations created in a Joram server
     * @param joramServerNode     Joram server node
     * @param jonasServerName the name of the JOnAS server to which the current JORAM server is connected
     * @param serverId            Joram server id
     * @param pResources The MessageResources for our localized messages
     * @param p_Request  The servlet request we are processing
     * @throws MalformedObjectNameException
     */
    public void getJoramResources(final TreeControlNode joramServerNode, final String jonasServerName, final String serverId,
            final MessageResources pResources, final HttpServletRequest p_Request) {

        ObjectName joramAdapterON;
        try {
            joramAdapterON = JoramObjectName.joramAdapter();
        } catch (MalformedObjectNameException e) {

            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get JORAM Adapter MBean: " + e);
            }
            return;
        }

        String joramServerNodeName = joramServerNode.getName();

        Short id = new Short(serverId);
        // Get all the destinations
        Object[] asParam = {
                id
        };
        String[] asSignature = {
                "short"
        };
        ArrayList destArray = new ArrayList();
        String[] destinations = null;
        try {
            destinations = (String[]) JonasManagementRepr.invoke(joramAdapterON, "getDestinations", asParam, asSignature, jonasServerName);
        } catch (ManagementException me) {
            // Maybe we are blocked on a remote server (Connection failed: Interrupted request)

            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get destinations of JORAM server having id " + id + ", " + me);
            }
            return;
        }
        for (int i = 0; i < destinations.length; i++) {
            String dest = destinations[i];
            ItemDestination destinationItem = getDestinationItem(dest, jonasServerName);
            if (destinationItem == null) {
                continue;
            }
            if ("Queue".equals(destinationItem.getType())) {
                // insert in head
                destArray.add(0, destinationItem);
            } else if ("Topic".equals(destinationItem.getType())) {
                // append
                destArray.add(destinationItem);
            }
        }

        // Add sub-nodes for destinations belonging to the server
        for (int i = 0; i < destArray.size(); i++) {
            ItemDestination item = (ItemDestination) destArray.get(i);
            String name = item.getName();
            String nameParamInAction = null;
            try {
                nameParamInAction = URLEncoder.encode(name, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                if (logger.isLoggable(BasicLevel.INFO)) {
                    logger.log(BasicLevel.INFO, "Can't get encoded value for destination " + name +  ". " + e);
                }
                return;
            }
            String type = item.getType();
            TreeControlNode destinationNode = null;
            String nodeName = null;
            String action = null;
            String icon = null;
            String label = null;
            if (type.equals("Queue")) {
                nodeName = joramServerNodeName + WhereAreYou.NODE_SEPARATOR + "joramqueue" + name;
                icon = "icon/jms_queue.gif";
                label = pResources.getMessage("treenode.joramplatform.queue") + " (" + name + ")";
                action = "EditJoramQueue.do?name=" + nameParamInAction + "&id=" + serverId;
            } else if (type.equals("Topic")) {
                nodeName = joramServerNodeName + WhereAreYou.NODE_SEPARATOR + "joramtopic" + name;
                icon = "icon/jms_topic.gif";
                label = pResources.getMessage("treenode.joramplatform.topic") + " (" + name + ")";
                action = "EditJoramTopic.do?name=" + nameParamInAction + "&id=" + serverId;
            }
            destinationNode = new TreeControlNode(nodeName, icon, label, action, "content", false);
            if (destinationNode != null) {
                addNode(joramServerNode, destinationNode);
            }
        }
    }

    /**
     * Create a ItemDestination object from a String structured as follows:
     *
     * joramClient:type=Queue/Topic,name=destName[#x.y.z]
     * @param joramDestination String containing destination OBJECT_NAME
     * @param serverName the name of the JOnAS server to which the current JORAM server is connected
     * @return ItemDestination containing name, type, id and ObjectName of the MBean associated to the corresponding destination
     * @throws MalformedObjectNameException could not construct destination ObjectName
     */
    public ItemDestination getDestinationItem(final String joramDestination, final String serverName) {
         ObjectName destinationOn = null;
        try {
            destinationOn = ObjectName.getInstance(joramDestination);
        } catch (MalformedObjectNameException e) {
            if (logger.isLoggable(BasicLevel.INFO)) {
                logger.log(BasicLevel.INFO, "Can't get JORAM Destination MBean: " + e);
            }
            return null;
        }
         ItemDestination destinationItem = new ItemDestination();
         destinationItem.setType(destinationOn.getKeyProperty("type"));
         if (JonasAdminJmx.hasMBeanName(destinationOn, serverName)) {
             destinationItem.setRegistered(true);
             destinationItem.setName((String) JonasManagementRepr.getAttribute(destinationOn, "AdminName", serverName));
             String agentName = (String) JonasManagementRepr.getAttribute(destinationOn, "Name", serverName);
             // destinationItem.setId(""); TODO
             destinationItem.setOn(destinationOn);
         }
         return destinationItem;
    }

    /**
     * Append nodes for all defined MBeans.
     *
     * @param domainNode Root node for the tree control
     * @param resources The MessageResources for our localized messages
     */
    public void getMBeans(final TreeControlNode domainNode, final MessageResources resources, final HttpServletRequest p_Request) {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        TreeControlNode nodeMBeans = new TreeControlNode(domainNode.getName()
                + WhereAreYou.NODE_SEPARATOR
                + "mbeans"
                , "icon/mbeans.gif"
                , resources.getMessage("treenode.allmbeans")
                , "ListMBeans.do", "content", false);
        if (addNode(domainNode, nodeMBeans)) {
            ArrayList[] als = JonasAdminJmx.getFamiliesMbeansLists(serverName);
            if (als[MbeanItem.FAMILY_J2EE].size() > 0) {
                getJ2eeMBeans(nodeMBeans, resources, als[MbeanItem.FAMILY_J2EE]);
            }
            if (als[MbeanItem.FAMILY_OWNER].size() > 0) {
                getOwnerMBeans(nodeMBeans, resources, als[MbeanItem.FAMILY_OWNER]);
            }
            if (als[MbeanItem.FAMILY_UNKNOWN].size() > 0) {
                getUnknownMBeans(nodeMBeans, resources, als[MbeanItem.FAMILY_UNKNOWN]);
            }
        }
    }

    /**
     * Append nodes for all defined Owner MBeans.
     *
     * @param p_ParentNode Parent node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_List The list of Mbeans
     */
    public void getOwnerMBeans(final TreeControlNode p_ParentNode, final MessageResources p_Resources
            , final ArrayList p_List) {

        TreeControlNode nodeMBeans = new TreeControlNode(p_ParentNode.getName()
                + WhereAreYou.NODE_SEPARATOR
                + "owner"
                , "icon/mbeans.gif"
                , p_Resources.getMessage("treenode.mbeans.owner")
                , "ListOwnerMBeans.do"
                , "content", false);
        if (!addNode(p_ParentNode, nodeMBeans)) {
            return;
        }
        // Sort list
        Collections.sort(p_List, new BeanComparator(new String[] {
                "domain", "type", "objectName"}));

        // Detail MBean node
        String sLastDomain = "";
        String sLastType = "";
        TreeControlNode nodeMBean = null;
        TreeControlNode nodeDomain = null;
        TreeControlNode nodeType = null;
        TreeControlNode nodeParent = null;
        OwnerMbeanItem oItem;

        Iterator it = p_List.iterator();
        while (it.hasNext()) {
            oItem = (OwnerMbeanItem) it.next();

            nodeParent = nodeMBeans;
            if (oItem.getDomain() != null) {
                // Domain node
                if (!oItem.getDomain().equals(sLastDomain)) {
                    sLastDomain = oItem.getDomain();
                    nodeDomain = new TreeControlNode(nodeParent.getName()
                            + WhereAreYou.NODE_SEPARATOR + oItem.getDomain(), "icon/mbeandomain.gif"
                            , oItem.getDomain(), null, "content", false);
                    addNode(nodeMBeans, nodeDomain);
                }
                nodeParent = nodeDomain;

                if (oItem.getType() != null) {
                    // Type node
                    if (!oItem.getType().equals(sLastType)) {
                        sLastType = oItem.getType();
                        nodeType = new TreeControlNode(nodeParent.getName()
                                + WhereAreYou.NODE_SEPARATOR + oItem.getType(), "icon/mbeantype.gif"
                                , oItem.getType(), null, "content", false);
                        addNode(nodeDomain, nodeType);
                    }
                    nodeParent = nodeType;
                }
            }

            // Mbean node
            nodeMBean = new TreeControlNode(p_ParentNode.getName()
                    + WhereAreYou.NODE_SEPARATOR
                    + oItem.getObjectName()
                    , "icon/mbean.gif"
                    , oItem.getObjectName()
                    , "ListMBeanDetails.do?select=" + encode(oItem.getObjectName())
                    , "content", false);
            addNode(nodeParent, nodeMBean);
        }
    }

    /**
     * Append nodes for all defined J2EE MBeans.
     *
     * @param p_ParentNode Parent node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_List The list of Mbeans
     */
    public void getJ2eeMBeans(final TreeControlNode p_ParentNode, final MessageResources p_Resources
            , final ArrayList p_List) {

        TreeControlNode nodeMBeans = new TreeControlNode(p_ParentNode.getName()
                + WhereAreYou.NODE_SEPARATOR
                + "j2ee"
                , "icon/mbeans.gif"
                , p_Resources.getMessage("treenode.mbeans.j2ee")
                , "ListJ2eeMBeans.do", "content", false);
        if (!addNode(p_ParentNode, nodeMBeans)) {
            return;
        }
        // Sort list
        Collections.sort(p_List, new BeanComparator(new String[] {
                "domain", "j2eeType", "name", "objectName"}));

        // Detail MBean node
        J2eeMbeanItem oItem;
        String sLastDomain = "";
        String sLastType = "";
        TreeControlNode nodeMBean = null;
        TreeControlNode nodeDomain = null;
        TreeControlNode nodeType = null;
        TreeControlNode nodeParent = null;

        Iterator it = p_List.iterator();
        while (it.hasNext()) {
            oItem = (J2eeMbeanItem) it.next();

            nodeParent = nodeMBeans;
            if (oItem.getDomain() != null) {
                // Domain node
                if (!oItem.getDomain().equals(sLastDomain)) {
                    sLastDomain = oItem.getDomain();
                    nodeDomain = new TreeControlNode(nodeParent.getName()
                            + WhereAreYou.NODE_SEPARATOR + oItem.getDomain(), "icon/mbeandomain.gif"
                            , oItem.getDomain(), null, "content", false);
                    addNode(nodeMBeans, nodeDomain);
                }
                nodeParent = nodeDomain;
            }
            if (oItem.getJ2eeType() != null) {
                // Type node
                if (!oItem.getJ2eeType().equals(sLastType)) {
                    sLastType = oItem.getJ2eeType();
                    nodeType = new TreeControlNode(nodeParent.getName()
                            + WhereAreYou.NODE_SEPARATOR + oItem.getJ2eeType(), "icon/mbeantype.gif"
                            , oItem.getJ2eeType(), null, "content", false);
                    addNode(nodeDomain, nodeType);
                }
                nodeParent = nodeType;
            }

            // Mbean node
            nodeMBean = new TreeControlNode(p_ParentNode.getName()
                    + WhereAreYou.NODE_SEPARATOR
                    + oItem.getObjectName()
                    , "icon/mbean.gif"
                    , oItem.getObjectName()
                    , "ListMBeanDetails.do?select=" + encode(oItem.getObjectName())
                    , "content", false);
            addNode(nodeParent, nodeMBean);

        }
    }

    /**
     * Append nodes for all defined Unknown MBeans.
     *
     * @param p_ParentNode Parent node for the tree control
     * @param p_Resources The MessageResources for our localized messages
     * @param p_List The list of Mbeans
     */
    public void getUnknownMBeans(final TreeControlNode p_ParentNode, final MessageResources p_Resources
            , final ArrayList p_List) {

        TreeControlNode nodeMBeans = new TreeControlNode(p_ParentNode.getName()
                + WhereAreYou.NODE_SEPARATOR
                + "unknown"
                , "icon/mbeans.gif"
                , p_Resources.getMessage("treenode.mbeans.unknown")
                , "ListUnknownMBeans.do", "content", false);
        if (!addNode(p_ParentNode, nodeMBeans)) {
            return;
        }
        // Sort list
        Collections.sort(p_List, new BeanComparator(new String[] {
                "domain", "objectName"}));

        // Detail MBean node
        MbeanItem oItem;
        String sLastDomain = "";
        TreeControlNode nodeMBean = null;
        TreeControlNode nodeDomain = null;
        TreeControlNode nodeType = null;
        TreeControlNode nodeParent = null;

        Iterator it = p_List.iterator();
        while (it.hasNext()) {
            oItem = (MbeanItem) it.next();

            nodeParent = nodeMBeans;
            if (oItem.getDomain() != null) {
                // Domain node
                if (!oItem.getDomain().equals(sLastDomain)) {
                    sLastDomain = oItem.getDomain();
                    nodeDomain = new TreeControlNode(nodeParent.getName()
                            + WhereAreYou.NODE_SEPARATOR + oItem.getDomain(), "icon/mbeandomain.gif"
                            , oItem.getDomain(), null, "content", false);
                    addNode(nodeMBeans, nodeDomain);
                }
                nodeParent = nodeDomain;

            }

            // Mbean node
            nodeMBean = new TreeControlNode(p_ParentNode.getName()
                    + WhereAreYou.NODE_SEPARATOR
                    + oItem.getObjectName()
                    , "icon/mbean.gif"
                    , oItem.getObjectName()
                    , "ListMBeanDetails.do?select=" + encode(oItem.getObjectName())
                    , "content", false);
            addNode(nodeParent, nodeMBean);

        }
    }

    /**
     * Append nodes Attributes and Operations for a defined MBean.
     *
     * @param nodeMBean The MBean node
     * @param onMBean The MBean Object name
     * @param resources Resource
     * @throws Exception
     */
    protected void getMBeanInfo(final TreeControlNode nodeMBean, final ObjectName onMBean
            , final MessageResources resources, final HttpServletRequest p_Request)
    throws Exception {
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(WhereAreYou.
                SESSION_NAME);
        String serverName = oWhere.getCurrentJonasServerName();
        // Get all infos of a MBean
        MBeanInfo oMBeanInfo = JonasManagementRepr.getMBeanInfo(onMBean, serverName);
        // Get attributes infos
        MBeanAttributeInfo[] aoMBeanAttributeInfo = oMBeanInfo.getAttributes();
        if (aoMBeanAttributeInfo.length > 0) {
            // Append attributes node
            TreeControlNode nodeAttributes = new TreeControlNode("Attributes"
                    + WhereAreYou.NODE_SEPARATOR + onMBean.toString(), "icon/JonasQuestion.gif"
                    , resources.getMessage("treenode.allmbeans.attributes"), null, "content", false);
            addNode(nodeMBean, nodeAttributes);
            // Loop to append each attribute node
            for (int i = 0; i < aoMBeanAttributeInfo.length; i++) {
                TreeControlNode nodeAttr = new TreeControlNode(String.valueOf(i)
                        + WhereAreYou.NODE_SEPARATOR + onMBean.toString() + WhereAreYou.NODE_SEPARATOR
                        + aoMBeanAttributeInfo[i].getName(), "icon/property.gif"
                        , aoMBeanAttributeInfo[i].getName(), null, "content", false);
                addNode(nodeAttributes, nodeAttr);
            }
        }
        // Get operations infos
        MBeanOperationInfo[] aoMBeanOperationInfo = oMBeanInfo.getOperations();
        if (aoMBeanOperationInfo.length > 0) {
            // Append operations node
            TreeControlNode nodeOperations = new TreeControlNode("Operations"
                    + WhereAreYou.NODE_SEPARATOR + onMBean.toString(), "icon/JonasQuestion.gif"
                    , resources.getMessage("treenode.allmbeans.operations"), null, "content", false);
            addNode(nodeMBean, nodeOperations);
            // Loop to append each operation node
            for (int i = 0; i < aoMBeanOperationInfo.length; i++) {
                TreeControlNode nodeOpe = new TreeControlNode(String.valueOf(i)
                        + WhereAreYou.NODE_SEPARATOR + onMBean.toString() + WhereAreYou.NODE_SEPARATOR
                        + aoMBeanOperationInfo[i].getName(), "icon/action.gif"
                        , aoMBeanOperationInfo[i].getName(), null, "content", false);
                addNode(nodeOperations, nodeOpe);
            }
        }
    }

    // MQ Connector support
    //----------------------
    /**
     *
     */
    public void getJonasMqConnectorPlatform(final TreeControlNode pServerNode,
            final String sServerName, final MessageResources pResources,
            final HttpServletRequest p_Request) {
        /*
         * retrieve the domain name
         */
        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(
                WhereAreYou.SESSION_NAME);
        String sDomainName = oWhere.getCurrentDomainName();

        TreeControlNode platformNode = new TreeControlNode(pServerNode
                .getName()
                + WhereAreYou.NODE_SEPARATOR + "jonasmqconnect",
                "icon/service_jms.gif", pResources
                .getMessage("treenode.joansmqconnect.name"),
                "JonasMqConnectPlatform.do", "content", false);

        if (!addNode(pServerNode, platformNode)) {
            return;
        }
        //ObjectName mqOnPattern = new ObjectName(sDomainName + ":type=JonasMQConnector,*");
        ObjectName[] mqOns = MqObjectNames.getConnectorsON(sDomainName, sServerName);
        for (int i = 0; i < mqOns.length; i++) {
            ObjectName on = mqOns[i];
            String connectorName = on.getKeyProperty("name");
            TreeControlNode serverNode = new TreeControlNode(platformNode
                    .getName()
                    + WhereAreYou.NODE_SEPARATOR
                    + "jonasmqconnector"
                    + WhereAreYou.NODE_SEPARATOR + connectorName,
                    "icon/jms_connector.gif", connectorName,
                    "JonasMqConnect.do?operation=view&connector=" + connectorName,
                    "content", false);
            if (addNode(platformNode, serverNode)) {
                getJonasMqDestinations(serverNode, connectorName, sServerName, pResources, p_Request);
            }
        }

    }
    /**
     *
     * Build the destination nodes
     */
    public void getJonasMqDestinations(final TreeControlNode pMQNode, final String connectorName,
            final String sServerName, final MessageResources pResources,
            final HttpServletRequest p_Request) {

        WhereAreYou oWhere = (WhereAreYou) p_Request.getSession().getAttribute(
                WhereAreYou.SESSION_NAME);
        String sDomainName = oWhere.getCurrentDomainName();
        //ObjectName mqDestPattern = new ObjectName(sDomainName + ":type=MQDestination,JonasMQConnector=" + connectorName+ ",*");
        //System.err.println("JOnASTreeBuilder querying " + mqDestPattern + " for server " + sServerName);
        ObjectName mqDestPattern = MqObjectNames.getDestinationsON(sDomainName, connectorName);
        Set destOns = JonasManagementRepr.queryNames(mqDestPattern, sServerName);
        for (Iterator i = destOns.iterator(); i.hasNext();) {
            ObjectName on = (ObjectName) i.next();
            String destName = on.getKeyProperty("name");
            boolean isTopic = ((Boolean) JonasManagementRepr.getAttribute(on, "IsTopic", sServerName)).booleanValue();
            TreeControlNode serverNode = new TreeControlNode(pMQNode.getName()
                    + WhereAreYou.NODE_SEPARATOR + "destination"
                    + WhereAreYou.NODE_SEPARATOR + destName,
                    "icon/" + (isTopic ? "jms_topic.gif" : "jms_queue.gif"), destName,
                    "JonasMqConnectDestinationEdit.do?operation=view&jndiName=" + destName + "&connector=" + connectorName,
                    "content", false);
            addNode(pMQNode, serverNode);
        }
    }

    /**
     * Add a new node in the tree as child of the current node
     * @param currentNode the current node
     * @param node the node to add
     * @return true if success, false if the new node couldn't be added
     */
    private boolean addNode(final TreeControlNode currentNode, final TreeControlNode node) {
        String nodeName = node.getName();
        try {
            currentNode.addChild(node);
        } catch(IllegalArgumentException iae) {
            //           the name of the new child node is not unique
            if (logger.isLoggable(BasicLevel.ERROR)) {
                logger.log(BasicLevel.ERROR, "Can't add node " + nodeName + " in the management tree as node name is not unique");
            }
            return false;
        }
        return true;
    }
    /**
     * Add a new node in the tree as child of the current node
     * @param currentNode the current node
     * @param node the node to add
     * @param offset Zero-relative offset at which the new node
     *  should be inserted
     * @return true if success, false if the new node couldn't be added
     */
    private boolean addNode(final TreeControlNode currentNode, final TreeControlNode node, final int offset) {
        String nodeName = node.getName();
        try {
            currentNode.addChild(offset, node);
        } catch(IllegalArgumentException iae) {
            // the name of the new child node is not unique
            if (logger.isLoggable(BasicLevel.ERROR)) {
                logger.log(BasicLevel.ERROR, "Can't add node " + nodeName + " in the management tree as node name is not unique");
            }
            return false;
        }
        return true;
    }

    private String encode(final String name) {
        try {
            return URLEncoder.encode(name, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
}
