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

package org.ow2.jonas.webapp.jonasadmin;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.apache.struts.util.MessageResources;
import org.ow2.jonas.lib.management.javaee.J2eeObjectName;
import org.ow2.jonas.lib.util.JonasObjectName;
import org.ow2.jonas.mail.MailService;
import org.ow2.jonas.webapp.jonasadmin.common.BeanComparator;
import org.ow2.jonas.webapp.jonasadmin.common.CatalinaObjectName;
import org.ow2.jonas.webapp.jonasadmin.logging.LoggerItem;
import org.ow2.jonas.webapp.jonasadmin.mbean.MbeanItem;
import org.ow2.jonas.webapp.jonasadmin.service.container.WebAppItem;

/**
 * Helper class supporting manipulation of MBeans (accessing MBeans).
 * @author Michel-Ange ANTON<p>
 * Contributors: Adriana Danes
 */
public class JonasAdminJmx {

// ----------------------------------------------------------- Constants

    private static Object s_Synchro = new Object();

// ----------------------------------------------------------- Constructors

    /**
     * Protected constructor to prevent instantiation.
     */
    protected JonasAdminJmx() {
    }

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

    /**
     * Replace any occurrence of the specified placeholder in the specified
     * template string with the specified replacement value.
     *
     * @param template Pattern string possibly containing the placeholder
     * @param placeholder Placeholder expression to be replaced
     * @param value Replacement value for the placeholder
     * @return A complete string
     */
    public static String replace(final String template, final String placeholder, final String value) {
        if (template == null) {
            return (null);
        }
        if ((placeholder == null) || (value == null)) {
            return (template);
        }
        String sRet = new String(template);
        while (true) {
            int index = sRet.indexOf(placeholder);
            if (index < 0) {
                break;
            }
            StringBuffer temp = new StringBuffer(sRet.substring(0, index));
            temp.append(value);
            temp.append(sRet.substring(index + placeholder.length()));
            sRet = temp.toString();
        }
        return (sRet);

    }

    public static ObjectName getArchiveConfigObjectName(final String domainName, final String serverName) {
        ObjectName onUtils = JonasObjectName.ArchiveConfig(domainName);
        return getFirstMbean(onUtils, serverName);
    }

    public static ObjectName getRarConfigObjectName(final String domainName, final String serverName) {
        ObjectName onUtils = JonasObjectName.RarConfig(domainName);
        return getFirstMbean(onUtils, serverName);
    }

    /**
     * Return the ObjectName corresponding to the J2EEServer managed object registered in the
     * current MBeanServer and belonging to a domain.
     * We should have one ObjectName corresponding to the current JOnAS server instance.
     * @param p_DomainName The name of the management domain.
     * @return an ObjectName which corresponds to a J2EEServer ObjectName pattern or null if
     * no J2EEServer found for the given management domain
     * (having <code>j2eeType</code> key property equal to <code>J2EEServer</code>)
     * @throws ManagementException if could not connect to the MBean server
     */
    public static ObjectName getJ2eeServerObjectName(final String p_DomainName, final String serverName) throws ManagementException {
        // Lookup for a J2EEServer managed object in the current MBeanServer
        ObjectName pattern_server_on = J2eeObjectName.J2EEServers(p_DomainName);
        ObjectName server_on = null;
        Iterator it = JonasManagementRepr.queryNames(pattern_server_on, serverName).iterator();
        if (it.hasNext()) {
            // Got one J2EEServer managed object ; normally should not be more than one
            server_on = (ObjectName) it.next();
        }
        return server_on;
    }

    /**
     * Return the ObjectName corresponding to the J2EEServer managed object registered in the
     * current MBeanServer. This method is used by EditTopAction to determine the list of
     * JOnAS servers registered in the current registry (this code is particular to the current
     * domain concept implementation).
     * We should have one ObjectName corresponding to the current JOnAS server instance.
     * @return an ObjectName which corresponds to a J2EEServer ObjectName pattern
     * (having <code>j2eeType</code> key property equal to <code>J2EEServer</code>)
     */
    public static ObjectName getJ2eeServerObjectName(final String serverName) {
        // Lookup for a J2EEServer managed object in the current MBeanServer
        ObjectName pattern_server_on = J2eeObjectName.J2EEServers();
        ObjectName server_on = null;
        Iterator it = JonasManagementRepr.queryNames(pattern_server_on, serverName).iterator();
        if (it.hasNext()) {
            // Got one J2EEServer managed object ; normally should not be more than one
            server_on = (ObjectName) it.next();
        }
        return server_on;
    }

    private static final String J2EEApplication = "J2EEApplication";
    private static final String AppClientModule = "AppClientModule";
    private static final String EJBModule = "EJBModule";
    private static final String WebModule = "WebModule";
    private static final String ResourceAdapterModule = "ResourceAdapterModule";
    /**
     * @param pObjectName an ObjectName
     * @return the j2eeType key property value
     */
    private static String getJ2eeType(final ObjectName pObjectName) {
        return pObjectName.getKeyProperty("j2eeType");
    }

    public static boolean isJ2EEApplication(final ObjectName pObjectName) {
        if (J2EEApplication.equals(getJ2eeType(pObjectName))) {
            return true;
        }
        return false;
    }
    public static boolean isAppClientModule(final ObjectName pObjectName) {
        if (AppClientModule.equals(getJ2eeType(pObjectName))) {
            return true;
        }
        return false;
    }
    public static boolean isEJBModule(final ObjectName pObjectName) {
        if (EJBModule.equals(getJ2eeType(pObjectName))) {
            return true;
        }
        return false;
    }
    public static boolean isWebModule(final ObjectName pObjectName) {
        if (WebModule.equals(getJ2eeType(pObjectName))) {
            return true;
        }
        return false;
    }
    public static boolean isResourceAdapterModule(final ObjectName pObjectName) {
        if (ResourceAdapterModule.equals(getJ2eeType(pObjectName))) {
            return true;
        }
        return false;
    }
    /**
     * Verify if the Mbean gotten by the query in the current MbeanServer exists.
     *
     * @param p_On Query Mbean name to search
     * @return true if MBean exists
     * @throws ManagementException
     */
    public static boolean hasMBeanName(final ObjectName p_On, final String serverName)
        throws ManagementException {
        synchronized (s_Synchro) {
            ArrayList al = new ArrayList();
            Iterator itNames = JonasManagementRepr.queryNames(p_On, serverName).iterator();
            if (itNames.hasNext()) {
                return true;
            }
            return false;
        }
    }

    /**
     * Return the first Mbean name gotten by the query in the current MbeanServer.
     *
     * @param p_On Query Mbean name to search
     * @return The first MBean name or null if not found
     * @throws ManagementException
     */
    public static String getFirstMBeanName(final ObjectName p_On, final String serverName)
        throws ManagementException {
        synchronized (s_Synchro) {
            ArrayList al = new ArrayList();
            Iterator itNames = JonasManagementRepr.queryNames(p_On, serverName).iterator();
            if (itNames.hasNext()) {
                return itNames.next().toString();
            }
            return null;
        }
    }

    /**
     * Return the list of Mbean name gotten by the query in the current MbeanServer.
     *
     * @param p_On Query Mbean name to search
     * @return A list of string Mbean name
     */
    public static List getListMBeanName(final ObjectName p_On, final String serverName) {
        synchronized (s_Synchro) {
            ArrayList<String> al = new ArrayList<String>();
            Iterator itNames = JonasManagementRepr.queryNames(p_On, serverName).iterator();
            while (itNames.hasNext()) {
                ObjectName item = (ObjectName) itNames.next();
                al.add(item.toString());
            }
            Collections.sort(al);
            return al;
        }
    }

    /**
     * Return the first <code>ObjectName</code> Mbean gotten by the query
     * in the current MbeanServer.
     *
     * @param p_On Query Mbean name to search
     * @return The first <code>ObjectName</code> or null if not found
     * @throws ManagementException
     */
    public static ObjectName getFirstMbean(final ObjectName p_On, final String serverName)
        throws ManagementException {
        synchronized (s_Synchro) {
            Iterator itNames = JonasManagementRepr.queryNames(p_On, serverName).iterator();
            if (itNames.hasNext()) {
                return (ObjectName) itNames.next();
            }
            return null;
        }
    }

    /**
     * Return the list of <code>ObjectName</code> Mbean gotten by the query
     * in the current MbeanServer.
     *
     * @param p_On Query Mbeans to search
     * @return The list of <code>ObjectName</code>
     * @throws ManagementException
     */
    public static List getListMbean(final ObjectName p_On, final String serverName)
        throws ManagementException {
        synchronized (s_Synchro) {
            ArrayList<ObjectName> al = new ArrayList<ObjectName>();
            Iterator itNames = JonasManagementRepr.queryNames(p_On, serverName).iterator();
            while (itNames.hasNext()) {
                al.add((ObjectName) itNames.next());
            }
            return al;
        }
    }

    /**
     * Extract the value of a key property from the MBean name.
     * This method is usefull when we have the String form and not the ObjectName
     * (avoid creating an ObjectName instance).
     * @param pName Name of the key property
     * @param pMBeanName Stringified ObjectName
     * @return The value or null if not found
     */
    public static String extractValueMbeanName(final String pName, final String pMBeanName) {
        String sValue = null;
        try {
            String sSearch = pName.trim() + "=";
            int iPos = pMBeanName.indexOf(sSearch);
            if (iPos > -1) {
                sValue = pMBeanName.substring(iPos + sSearch.length());
                iPos = sValue.indexOf(",");
                if (iPos > -1) {
                    sValue = sValue.substring(0, iPos);
                }
            }
        } catch (NullPointerException e) {
            // none
            sValue = null;
        }
        return sValue;
    }

    /**
     * Extract the filename of complete path.
     *
     * @param p_Path Complete path (directory and filename)
     * @return The filename or null
     */
    public static String extractFilename(String p_Path) {
        String sFilename = null;
        try {
            int lastCharIndex = p_Path.length() - 1;
            if (p_Path.lastIndexOf("/") == lastCharIndex) {
                // the path ends with "/"
                p_Path = p_Path.substring(0, lastCharIndex);
            }
            int iPosSeparator = p_Path.lastIndexOf("/");
            if (iPosSeparator < 0) {
                iPosSeparator = p_Path.lastIndexOf("\\");
                if (iPosSeparator < 0) {
                    sFilename = new String(p_Path);
                }
                else {
                    sFilename = p_Path.substring(iPosSeparator + 1);
                }
            }
            else {
                sFilename = p_Path.substring(iPosSeparator + 1);
            }
            if (sFilename.length() > 0) {
                int iPos_1 = p_Path.indexOf(DIR_AUTOLOAD + "/" + sFilename);
                int iPos_2 = p_Path.indexOf(DIR_AUTOLOAD + "\\" + sFilename);
                if (iPos_1 > -1) {
                    sFilename = DIR_AUTOLOAD + "/" + sFilename;
                }
                else if (iPos_2 > -1) {
                    sFilename = DIR_AUTOLOAD + "\\" + sFilename;
                }
            }
            else {
                sFilename = null;
            }
        }
        catch (NullPointerException e) {
            // none action
            sFilename = null;
        }
        return sFilename;
    }

    /**
     *
     */
    private static String DIR_RARS = "rars";
    private static String DIR_AUTOLOAD = "autoload";
    private static String DIR_CONF = "conf";

    private static ArrayList getFilenames(final String p_Directory, final String p_Extension) {
        ArrayList al = new ArrayList();
        String sExt = "." + p_Extension.toLowerCase();
        String sFile;

        File oFile = new File(p_Directory);
        String[] asFiles = oFile.list();
        int iPos;
        if (asFiles != null) {
            for (int i = 0; i < asFiles.length; i++) {
                oFile = new File(p_Directory, asFiles[i]);
                if (oFile.isFile() == true) {
                    sFile = oFile.getName().toLowerCase();
                    iPos = sFile.lastIndexOf(sExt);
                    if (iPos > -1) {
                        if (iPos == (sFile.length() - sExt.length())) {
                            al.add(oFile.getName());
                        }
                    }
                }
            }
        }
        Collections.sort(al);
        return al;
    }

    private static ArrayList getDirectories(final String p_Directory) {
        ArrayList al = new ArrayList();
        String sFile;

        File oFile = new File(p_Directory);
        String[] asFiles = oFile.list();

        if (asFiles != null) {
            for (int i = 0; i < asFiles.length; i++) {
                oFile = new File(p_Directory, asFiles[i]);
                if (oFile.isDirectory() == true) {
                    al.add(oFile.getName());
                }
            }
        }
        Collections.sort(al);
        return al;
    }

    private static void appendDirectory(final ArrayList p_List, final String p_Dir) {
        String sDir = p_Dir + "/";
        for (int i = 0; i < p_List.size(); i++) {
            p_List.set(i, sDir + p_List.get(i));
        }
    }

    public static ArrayList getFilesDeployable(final String domainName, final String serverName)
    throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList<String> al = (ArrayList<String>) JonasManagementRepr.getAttribute(on, "deployableFiles", serverName);
        // Sort
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of JAR filename ready to deploy in the current server.
     *
     * @return The list of JAR filename.
     * @throws ManagementException
     */
    public static ArrayList getJarFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList<String> al = (ArrayList<String>) JonasManagementRepr.getAttribute(on, "deployableJars", serverName);
        // Sort
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of deployed JAR filename in the current server.
     *
     * @return The list of JAR filename.
     * @throws ManagementException
     */
    public static ArrayList getJarFilesDeployed(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList<String> al = (ArrayList<String>) JonasManagementRepr.getAttribute(on, "deployedJars", serverName);
        // Sort
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of EAR filename ready to deploy in the current server.
     *
     * @return The list of EAR filename.
     * @throws ManagementException
     */
    public static ArrayList getEarFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList<String> al = (ArrayList<String>) JonasManagementRepr.getAttribute(on, "deployableEars", serverName);
        // Sort
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of WAR filename ready to deploy in the current server.
     *
     * @return The list of WAR filename.
     * @throws ManagementException
     */
    public static ArrayList getWarFilesDeployable(final String domainName, final String serverName)
    throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList<String> al = (ArrayList<String>) JonasManagementRepr.getAttribute(on, "deployableWars", serverName);
        // Sort
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of RAR filename ready to deploy in the current server.
     *
     * @return The list of RAR filename.
     * @throws ManagementException
     */
    public static ArrayList getRarFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList al = (ArrayList) JonasManagementRepr.getAttribute(on, "deployableRars", serverName);
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of deployed WAR filename in the current server.
     *
     * @return The list of WAR filename.
     * @throws ManagementException
     */
    public static ArrayList getWarFilesDeployed(final String domainName, final String serverName)
    throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList al = (ArrayList) JonasManagementRepr.getAttribute(on, "deployedWars", serverName);
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of deployed EAR filename in the current server.
     *
     * @return The list of EAR filename.
     * @throws ManagementException
     */
    public static ArrayList getEarFilesDeployed(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList al = (ArrayList) JonasManagementRepr.getAttribute(on, "deployedEars", serverName);
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of deployed RAR filename in the current server.
     *
     * @return The list of RAR filename.
     * @throws ManagementException
     */
    public static ArrayList getRarFilesDeployed(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList al = (ArrayList) JonasManagementRepr.getAttribute(on, "deployedRars", serverName);
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of deployed RAR filename in the current server.
     *
     * @return The list of RAR filename.
     * @throws ManagementException
     */
    public static ArrayList getFilesDeployed(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = J2eeObjectName.J2EEServer(domainName, serverName);
        ArrayList al = (ArrayList) JonasManagementRepr.getAttribute(on, "deployedFiles", serverName);
        Collections.sort(al);
        return al;
    }
    /**
     * Prepare a list of containers to diplay.
     * Deleting prefix root container directory, sorting the list.
     * @param p_Containers The list of containers
     * @param p_ContainerDir The root container directory
     * @param p_EarDir The root ear directory or null
     * @return The list of containers ready to display
     */
    public static ArrayList prepareContainersToDisplay(final ArrayList p_Containers
        , final String p_ContainerDir, final String p_EarDir) {
        int iPos;
        String sPath;
        boolean bAdd;
        ArrayList al = new ArrayList();
        for (int i = 0; i < p_Containers.size(); i++) {
            // Delete prefix root container directory
            sPath = p_Containers.get(i).toString();
            iPos = sPath.indexOf(p_ContainerDir);
            if (iPos > -1) {
                sPath = sPath.substring(p_ContainerDir.length());
            }
            // Delete suffix slash
            if (sPath.endsWith("/") == true) {
                sPath = sPath.substring(0, sPath.length() - 1);
            }
            // Flag to filter
            bAdd = true;
            // Filter Jar or War include in Ear
            if (p_EarDir != null) {
                iPos = sPath.indexOf(p_EarDir);
                if (iPos > -1) {
                    bAdd = false;
                }

            }
            if (bAdd == true) {
                al.add(sPath);
            }
        }
        // Sort
        Collections.sort(al);
        return al;
    }

    private static ArrayList getFilesDeployed(final ObjectName on, final String serverName)
        throws ManagementException {
        ArrayList alDeployed = new ArrayList();
        String sPath;
        String sFile;
        Iterator itNames = JonasAdminJmx.getListMBeanName(on, serverName).iterator();
        while (itNames.hasNext()) {
            sPath = JonasAdminJmx.extractValueMbeanName("fname", itNames.next().toString());
            sFile = JonasAdminJmx.extractFilename(sPath);
            if (sFile != null) {
                alDeployed.add(sFile);
            }
        }
        Collections.sort(alDeployed);
        return alDeployed;

    }

    /**
     * Return the list of Mail factory files ready to deploy in the current server.
     *
     * @return The list of Mail factory properties filenames.
     * @throws ManagementException
     */
    public static ArrayList getMailFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = JonasObjectName.mailService(domainName);
        return (ArrayList) JonasManagementRepr.invoke(on, "getMailFactoryPropertiesFiles", new Object[0], new String[0], serverName);
    }

    /**
         * Return the list of MimePartDataSource Mail factory files ready to deploy in the current server.
     *
     * @return The list of MimePartDataSource Mail factory properties filenames.
     * @throws ManagementException
     */
    public static ArrayList getMimePartMailFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = JonasObjectName.mailService(domainName);
        return (ArrayList) JonasManagementRepr.invoke(on
            , "getMimePartMailFactoryPropertiesFiles", new Object[0], new String[0], serverName);
    }

    /**
     * Return the list of Session Mail factory files ready to deploy in the current server.
     *
     * @return The list of Session Mail factory properties filenames.
     * @throws ManagementException
     */
    public static ArrayList getSessionMailFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = JonasObjectName.mailService(domainName);
        return (ArrayList) JonasManagementRepr.invoke(on, "getSessionMailFactoryPropertiesFiles", new Object[0], new String[0], serverName);
    }

    /**
     * Return the list of deployed MimePartDataSource Mail factories in the current server.
     *
     * @param p_WhereAreYou The container WhereAreYou
     * @return The list of MimePartDataSource Mail factory filename.
     * @throws ManagementException
     */
    public static ArrayList getMimePartMailFilesDeployed(final WhereAreYou p_WhereAreYou)
        throws ManagementException {
        ArrayList alDeployed = new ArrayList();
        String sName;
        String domainName = p_WhereAreYou.getCurrentDomainName();
        String serverName = p_WhereAreYou.getCurrentJonasServerName();
        ObjectName on = J2eeObjectName.JavaMailResources(domainName, serverName
            , MailService.MIMEPART_PROPERTY_TYPE);
        Iterator itNames = JonasManagementRepr.queryNames(on, serverName).iterator();
        while (itNames.hasNext()) {
            ObjectName it_on = (ObjectName) itNames.next();
            sName = it_on.getKeyProperty("name");
            if (sName != null) {
                alDeployed.add(sName);
            }
        }
        Collections.sort(alDeployed);
        return alDeployed;
    }

    /**
     * Return the list of deployed Session Mail factories in the current server.
     *
     * @param p_WhereAreYou The container WhereAreYou
     * @return The list of Session Mail factory filename.
     * @throws ManagementException
     */
    public static ArrayList getSessionMailFilesDeployed(final WhereAreYou p_WhereAreYou)
        throws ManagementException {
        ArrayList alDeployed = new ArrayList();
        String sName;
        String domainName = p_WhereAreYou.getCurrentDomainName();
        String serverName = p_WhereAreYou.getCurrentJonasServerName();
        ObjectName on = J2eeObjectName.JavaMailResources(domainName, serverName
            , MailService.SESSION_PROPERTY_TYPE);
        Iterator itNames = JonasManagementRepr.queryNames(on, serverName).iterator();
        while (itNames.hasNext()) {
            ObjectName it_on = (ObjectName) itNames.next();
            sName = it_on.getKeyProperty("name");
            if (sName != null) {
                alDeployed.add(sName);
            }
        }
        Collections.sort(alDeployed);
        return alDeployed;
    }

    /**
     * Return the list of deployed Mail factories in the current server.
     *
     * @param p_WhereAreYou The container WhereAreYou
     * @return The list of Mail factory filename.
     * @throws ManagementException
     */
    public static ArrayList getMailFilesDeployed(final WhereAreYou p_WhereAreYou)
        throws ManagementException {
        ArrayList alDeployed = getSessionMailFilesDeployed(p_WhereAreYou);
        alDeployed.addAll(getMimePartMailFilesDeployed(p_WhereAreYou));
        Collections.sort(alDeployed);
        return alDeployed;
    }

    /**
     * Return the list of Datasource properties files ready to deploy in the current server.
     *
     * @return The list of Datasource properties filenames.
     * @throws ManagementException Could not get managzement info from the MBeanServer
     */
    public static ArrayList getDatasourceFilesDeployable(final String domainName, final String serverName)
        throws ManagementException {
        ObjectName on = JonasObjectName.databaseService(domainName);
        return (ArrayList) JonasManagementRepr.getAttribute(on, "DataSourcePropertiesFiles", serverName);
    }

    /**
     * Return the list of deployed Datasources in the current server.
     * @param domainName Current domain name
     * @param serverName Current server name
     * @return The list of Datasource filename.
     * @throws ManagementException Could not get managzement info from the MBeanServer
     */
    public static ArrayList getDatasourceFilesDeployed(final String domainName, final String serverName)
        throws ManagementException {

        ArrayList<String> alDeployed = new ArrayList<String>();
        ObjectName ons = J2eeObjectName.JDBCDataSources(domainName, serverName);
        // iterate ovent the JDBCDataSources within the current server
        Iterator itNames = JonasManagementRepr.queryNames(ons, serverName).iterator();
        String sName = null;
        while (itNames.hasNext()) {
            ObjectName on = (ObjectName) itNames.next();
            sName = on.getKeyProperty("name");
            if (sName != null) {
                alDeployed.add(sName);
            }
        }
        Collections.sort(alDeployed);
        return alDeployed;
    }

    /**
     * Return the list of Datasource dependences for a given datasource name in the current server.
     *
     * @param pDatasourceName The name of the datasource
     * @param domainName Current domain name
     * @param serverName Current server name
     * @return The list of Datasource dependence (a list of names corresponding to EJBs using this datasource).
     * @throws ManagementException Could not get managzement info from the MBeanServer
     * @throws MalformedObjectNameException
     */
    public static ArrayList getDatasourceDependences(final String pDatasourceName, final String domainName, final String serverName)
        throws ManagementException {
        ObjectName jdbcDatasource = J2eeObjectName.getJDBCDataSource(domainName, serverName, pDatasourceName);
        String[] asParam = new String[1];
        String[] asSignature = new String[1];
        asSignature[0] = "java.lang.String";
        ArrayList<String> al = new ArrayList<String>();
        asParam[0] = (String) JonasManagementRepr.getAttribute(jdbcDatasource, "jndiName", serverName);
        if (JonasManagementRepr.isRegistered(JonasObjectName.ejbService(domainName), serverName)) {
            String sName;
            Iterator it = ((java.util.Set) JonasManagementRepr.invoke(JonasObjectName.ejbService(domainName)
                , "getDataSourceDependence", asParam, asSignature, serverName)).iterator();
            while (it.hasNext()) {
                sName = JonasAdminJmx.extractValueMbeanName(",name", it.next().toString());
                if (sName != null) {
                    al.add(sName);
                }
            }
            Collections.sort(al);
        }
        return al;
    }

    /**
     * Return the list of Mail factory dependences in the current server for a given factory name.
     *
     * @param p_MailFactoryName The name of the mail factory
     * @param p_WhereAreYou The container WhereAreYou
     * @return The list of Mail factory dependences (a list of names corresponding to EJBs using this mail factory).
     * @throws ManagementException
     */
    public static ArrayList getMailFactoryDependences(final String p_MailFactoryName
        , final WhereAreYou p_WhereAreYou)
        throws ManagementException {
        String jndiName = null;
        String domainName = p_WhereAreYou.getCurrentDomainName();
        String serverName = p_WhereAreYou.getCurrentJonasServerName();
        String type = MailService.SESSION_PROPERTY_TYPE;
        // create an MBean name with the given MailFactory name
        // - try with a session Mail Factory type
        ObjectName on = J2eeObjectName.JavaMailResource(domainName, p_MailFactoryName, serverName
            , type);
        //ObjectName on = JonasObjectName.sessionMailFactory(p_MailFactoryName);
        if (JonasManagementRepr.isRegistered(on, serverName) != true) {
            // in this case, this is a MimePartDataSource mail factory
            //on = JonasObjectName.mimeMailFactory(p_MailFactoryName);
            type = MailService.MIMEPART_PROPERTY_TYPE;
            on = J2eeObjectName.JavaMailResource(domainName, p_MailFactoryName, serverName, type);
        }
        jndiName = (String) JonasManagementRepr.getAttribute(on, "Name", serverName);

        String[] asParam = new String[1];
        String[] asSignature = new String[1];
        asSignature[0] = "java.lang.String";
        ArrayList<String> al = new ArrayList<String>();
        asParam[0] = jndiName;
        if (JonasManagementRepr.isRegistered(JonasObjectName.ejbService(domainName), serverName) == true) {
            String sName;
            Iterator it = ((java.util.Set) JonasManagementRepr.invoke(JonasObjectName.ejbService(domainName)
                , "getMailFactoryDependence", asParam, asSignature, serverName)).iterator();
            while (it.hasNext()) {
                sName = JonasAdminJmx.extractValueMbeanName(",name", it.next().toString());
                if (sName != null) {
                    al.add(sName);
                }
            }
            Collections.sort(al);
        }
        return al;
    }

    /**
     * Return the list of deployed Session Mail Factories in the current server.
     *
     * @param p_WhereAreYou The container WhereAreYou
     * @return The list
     * @throws ManagementException
     */
    public static ArrayList getSessionMailFactoriesDeployed(final WhereAreYou p_WhereAreYou)
        throws ManagementException {

        ArrayList<String> alDeployed = new ArrayList<String>();
        String sName;
        String domainName = p_WhereAreYou.getCurrentDomainName();
        String serverName = p_WhereAreYou.getCurrentJonasServerName();
        String type = MailService.SESSION_PROPERTY_TYPE;

        ObjectName any_on = J2eeObjectName.JavaMailResources(domainName, serverName, type);
        Iterator itNames = JonasManagementRepr.queryNames(any_on, serverName).iterator();
        while (itNames.hasNext()) {
            ObjectName on = (ObjectName) itNames.next();
            sName = on.getKeyProperty("name");
            if (sName != null) {
                alDeployed.add(sName);
            }
        }

        Collections.sort(alDeployed);
        return alDeployed;
    }

    /**
     * Return the list of deployed MimePartDatasource Mail Factories in the current server.
     *
     * @param p_WhereAreYou The container WhereAreYou
     * @return The list
     * @throws ManagementException
     */
    public static ArrayList getMimeMailPartFactoriesDeployed(final WhereAreYou p_WhereAreYou)
        throws ManagementException {
        ArrayList<String> alDeployed = new ArrayList<String>();
        String sName;
        String domainName = p_WhereAreYou.getCurrentDomainName();
        String serverName = p_WhereAreYou.getCurrentJonasServerName();
        String type = MailService.MIMEPART_PROPERTY_TYPE;

        ObjectName any_on = J2eeObjectName.JavaMailResources(domainName, serverName, type);
        Iterator itNames = JonasManagementRepr.queryNames(any_on, serverName).iterator();
        while (itNames.hasNext()) {
            ObjectName on = (ObjectName) itNames.next();
            sName = on.getKeyProperty("name");
            if (sName != null) {
                alDeployed.add(sName);
            }
        }
        Collections.sort(alDeployed);
        return alDeployed;
    }

    /**
     * Return the list of Security Memory Factories in the current server.
     *
     * @return The list of Security Memory Factories
     * @throws MalformedObjectNameException
     */
    public static ArrayList getSecurityMemoryFactories(final String domainName, final String serverName)
        throws MalformedObjectNameException {
        String sName;
        ArrayList<String> al = new ArrayList<String>();
        Iterator itNames = getListMBeanName(JonasObjectName.allSecurityMemoryFactories(domainName), serverName).iterator();
        while (itNames.hasNext()) {
            sName = JonasAdminJmx.extractValueMbeanName(",name", itNames.next().toString());
            if (sName != null) {
                al.add(sName);
            }
        }
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of Security Datasource Factories in the current server.
     *
     * @return The list of Security Datasource Factories
     * @throws MalformedObjectNameException
     */
    public static ArrayList getSecurityDatasourceFactories(final String domainName, final String serverName)
        throws MalformedObjectNameException {
        String sName;
        ArrayList<String> al = new ArrayList<String>();
        Iterator itNames = getListMBeanName(JonasObjectName.allSecurityDatasourceFactories(domainName), serverName).
            iterator();
        while (itNames.hasNext()) {
            sName = JonasAdminJmx.extractValueMbeanName(",name", itNames.next().toString());
            if (sName != null) {
                al.add(sName);
            }
        }
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of Security Ldap Factories in the current server.
     *
     * @return The list of Security Ldap Factories
     * @throws MalformedObjectNameException
     */
    public static ArrayList getSecurityLdapFactories(final String domainName, final String serverName)
        throws MalformedObjectNameException {
        String sName;
        ArrayList<String> al = new ArrayList<String>();
        Iterator itNames = getListMBeanName(JonasObjectName.allSecurityLdapFactories(domainName), serverName).iterator();
        while (itNames.hasNext()) {
            sName = JonasAdminJmx.extractValueMbeanName(",name", itNames.next().toString());
            if (sName != null) {
                al.add(sName);
            }
        }
        Collections.sort(al);
        return al;
    }

    /**
     * Return the SubType of a Security Factory in the current server.
     *
     * @param p_NameFactory The factory name to find
     * @return The SubType or null if not found
     * @throws ManagementException
     * @throws MalformedObjectNameException
     */
    public static String findSecurityFactorySubType(final String p_NameFactory, final String domainName, final String serverName)
        throws MalformedObjectNameException {
        String sName;
        String sSubType = null;
        ObjectName on = null;

        Iterator itNames = getListMBeanName(JonasObjectName.allSecurityFactories(domainName), serverName).iterator();
        while (itNames.hasNext()) {
            on = new ObjectName(itNames.next().toString());
            sName = on.getKeyProperty("name");
            if (p_NameFactory.equals(sName) == true) {
                sSubType = on.getKeyProperty("subtype");
                break;
            }
        }
        return sSubType;
    }

    /**
     * Return the list of all users in a resource.
     * @param domainName the domain name
     * @param p_Resource The resource
     * @return The list of users
     * @throws ManagementException
     * @throws MalformedObjectNameException
     */
    public static ArrayList getUsers(final String domainName, final String p_Resource, final String serverName)
        throws ManagementException, MalformedObjectNameException {
        String sName;
        ArrayList<String> al = new ArrayList<String>();
        Iterator itNames = getListMBeanName(JonasObjectName.allUsers(domainName, p_Resource), serverName).iterator();
        while (itNames.hasNext()) {
            sName = JonasAdminJmx.extractValueMbeanName(",name", itNames.next().toString());
            if (sName != null) {
                al.add(sName);
            }
        }
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of all roles in a resource.
     * @param domainName the domain name
     * @param p_Resource The resource
     * @return The list of roles
     * @throws ManagementException
     * @throws MalformedObjectNameException
     */
    public static ArrayList getRoles(final String domainName, final String p_Resource, final String serverName)
        throws ManagementException, MalformedObjectNameException {
        String sName;
        ArrayList<String> al = new ArrayList<String>();
        Iterator itNames = getListMBeanName(JonasObjectName.allRoles(domainName, p_Resource), serverName).iterator();
        while (itNames.hasNext()) {
            sName = JonasAdminJmx.extractValueMbeanName(",name", itNames.next().toString());
            if (sName != null) {
                al.add(sName);
            }
        }
        Collections.sort(al);
        return al;
    }

    /**
     * Return the list of all groups in a resource.
     * @param domainName the domain name
     * @param p_Resource The resource
     * @return The list of groups
     * @throws ManagementException
     * @throws MalformedObjectNameException
     */
    public static ArrayList getGroups(final String domainName, final String p_Resource, final String serverName)
        throws ManagementException, MalformedObjectNameException {
        String sName;
        ArrayList<String> al = new ArrayList<String>();
        Iterator itNames = getListMBeanName(JonasObjectName.allGroups(domainName, p_Resource), serverName).iterator();
        while (itNames.hasNext()) {
            sName = JonasAdminJmx.extractValueMbeanName(",name", itNames.next().toString());
            if (sName != null) {
                al.add(sName);
            }
        }
        Collections.sort(al);
        return al;
    }

    /**
     * Return the Queue destinations list.
     * @return The list
     */
    public static ArrayList getQueuesList(final String domainName, final String serverName) {
        synchronized (s_Synchro) {
            ObjectName jmsServMB = JonasObjectName.jmsService(domainName);
            Set queues = (Set) JonasManagementRepr.getAttribute(jmsServMB
                , "AllJmsQueueDestinationNames", serverName);
            ArrayList<Object> al = new ArrayList<Object>();
            Iterator itNames = queues.iterator();
            while (itNames.hasNext()) {
                al.add(itNames.next());
            }
            return al;
        }
    }

    /**
     * Return the Topic destinations list.
     * @return The list
     */
    public static ArrayList getTopicsList(final String domainName, final String serverName) {
        synchronized (s_Synchro) {
            ObjectName jmsServMB = JonasObjectName.jmsService(domainName);
            Set topics = (Set) JonasManagementRepr.getAttribute(jmsServMB
                , "AllJmsTopicDestinationNames", serverName);
            ArrayList<Object> al = new ArrayList<Object>();
            Iterator itNames = topics.iterator();
            while (itNames.hasNext()) {
                al.add(itNames.next());
            }
            return al;
        }
    }

    /**
     * Return the default Connection Factories.
     *
     * @param p_Resources The messages
     * @return The list
     */
    public static ArrayList getConnectionFactoriesList(final MessageResources p_Resources, final String domainName, final String serverName) {
        synchronized (s_Synchro) {
            ObjectName jmsServMB = JonasObjectName.jmsService(domainName);
            String cfName = (String) JonasManagementRepr.getAttribute(jmsServMB
                , "DefaultConnectionFactoryName", serverName);
            String tcfName = (String) JonasManagementRepr.getAttribute(jmsServMB
                , "DefaultTopicConnectionFactoryName", serverName);
            String qcfName = (String) JonasManagementRepr.getAttribute(jmsServMB
                , "DefaultQueueConnectionFactoryName", serverName);
            ArrayList<JmsConnFact> al = new ArrayList<JmsConnFact>();
            String comment = p_Resources.getMessage("tab.connfact.defaultconnfact");
            JmsConnFact cf = new JmsConnFact(cfName, comment);
            al.add(cf);
            comment = p_Resources.getMessage("tab.connfact.defaulttopicconnfact");
            cf = new JmsConnFact(tcfName, comment);
            al.add(cf);
            comment = p_Resources.getMessage("tab.connfact.defaultqueueconnfact");
            cf = new JmsConnFact(qcfName, comment);
            al.add(cf);
            return al;
        }
    }

    /**
     * Return the list of all used loggers in this JOnAS server.
     * @param p_Resources The used message resource
     * @param p_WhereAreYou The used WhereAreYou instance
     * @param p_Action True to get the action (to use directly in jsp) or False to get the same action but in forward (write in the file struts-config.xml)
     * @return The list of loggers
     * @throws ManagementException
     */
    public static ArrayList getLoggers(final MessageResources p_Resources, final WhereAreYou p_WhereAreYou
        , final boolean p_Action)
        throws MalformedObjectNameException {
        String serverName = p_WhereAreYou.getCurrentJonasServerName();
        ArrayList<LoggerItem> al = new ArrayList<LoggerItem>();
        String sActionForward;
        // Get JONAS logger
        if (p_Action == true) {
            sActionForward = "EditLoggingJonas.do";
        }
        else {
            sActionForward = "ActionEditLoggingJonas";
        }
        String itemName = p_Resources.getMessage("logger.jonas.name");
        String type = LoggerItem.LOGGER_JONAS;
        LoggerItem li = new LoggerItem(itemName, type, sActionForward);
        al.add(li);
        // Get Catalina Logger
        if (p_WhereAreYou.isCatalinaServer() == true) {
            ObjectName on = CatalinaObjectName.catalinaAccessLogValves(p_WhereAreYou.
                getCurrentCatalinaDomainName());

            Iterator it = getListMbean(on, serverName).iterator();
            while (it.hasNext()) {
                ObjectName oItem = (ObjectName) it.next();
                if (p_Action) {
                    sActionForward = "EditCatalinaAccessLogger.do?select=" + oItem.toString();
                }
                else {
                    sActionForward = "ActionEditCatalinaAccessLogger";
                }
                itemName = p_Resources.getMessage("logger.catalina.access.name");
                String hostName = oItem.getKeyProperty("host");
                String containerName = null;
                String containerType = null;
                String containerLabel = null;
                if (hostName == null) {
                    type = LoggerItem.LOGGER_CATALINA_ACCESS_ENGINE;
                    containerType = p_Resources.getMessage("label.loggers.container.engine");
                    containerName = p_Resources.getMessage("label.loggers.container.engine.name");
                    containerLabel = containerName;
                } else {
                    String pathName = oItem.getKeyProperty("path");
                    if (pathName != null) {
                        type = LoggerItem.LOGGER_CATALINA_ACCESS_CONTEXT;
                        containerName = pathName;
                        containerType = p_Resources.getMessage("label.loggers.container.context");
                        containerLabel = WebAppItem.extractLabelPathContext(containerName, p_WhereAreYou.getCurrentCatalinaDefaultHostName());
                    } else {
                        type = LoggerItem.LOGGER_CATALINA_ACCESS_HOST;
                        containerName = hostName;
                        containerType = p_Resources.getMessage("label.loggers.container.host");
                        containerLabel = containerName;
                    }
                }
                itemName = itemName.concat(" " + containerLabel);
                li = new LoggerItem(itemName, type, sActionForward, oItem.toString(), containerType, containerName);
                al.add(li);
            }
        }
        BeanComparator beanComparator = new BeanComparator(new String[]{"name"});
        // sort
        Collections.sort(al, beanComparator);
        return al;
    }

    /**
     * Create a list for each family of Mbean.
     *
     * @return An array of lists
     * @throws ManagementException
     */
    public static ArrayList getMbeansLists(final String serverName)
        throws ManagementException {

        MbeanItem oItem;

        // Create the new list
        ArrayList<MbeanItem> al = new ArrayList<MbeanItem>();
        // Dispath each Mbean in its list
        Iterator it = JonasAdminJmx.getListMbean(null, serverName).iterator();
        while (it.hasNext()) {
            oItem = MbeanItem.build((ObjectName) it.next());
            al.add(oItem);
        }
        return al;
    }

    /**
     * Create a list for each family of Mbean.
     *
     * @return An array of lists
     * @throws ManagementException
     */
    public static ArrayList[] getFamiliesMbeansLists(final String serverName)
        throws ManagementException {

        MbeanItem oItem;

        // Create the new lists
        ArrayList[] als = new ArrayList[3];
        for (int i = 0; i < MbeanItem.SIZE_FAMILIES; i++) {
            als[i] = new ArrayList();
        }
        // Dispath each Mbean in its list
        Iterator it = JonasAdminJmx.getListMbean(null, serverName).iterator();
        while (it.hasNext()) {
            oItem = MbeanItem.build((ObjectName) it.next());
            int i = oItem.getFamily();
            als[i].add(oItem);
        }
        return als;
    }

    /**
     * Get all StatefulSessionBeans in a server
     * @param serverName the server name
     * @return the number of StatefulSessionBeans
     */
    public static int getTotalNbStatefulSessionBeans(final String domainName, final String serverName) {
        int nb = 0;
        ObjectName moduleOns = J2eeObjectName.getEJBModules(domainName, serverName);
        Iterator it = null;
        synchronized (s_Synchro) {
            it = JonasManagementRepr.queryNames(moduleOns, serverName).iterator();
        }
        while (it.hasNext()) {
            ObjectName moduleOn = (ObjectName) it.next();
            String[] ejbs = (String[]) JonasManagementRepr.getAttribute(moduleOn, "ejbs", serverName);
            for (int i = 0; i < ejbs.length; i++) {
                String ejbON = ejbs[i];
                try {
                    ObjectName ejbOn = ObjectName.getInstance(ejbON);
                    String ejbType = ejbOn.getKeyProperty("j2eeType");
                    if ("StatefulSessionBean".equals(ejbType)) {
                        nb++;
                    }
                } catch (MalformedObjectNameException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NullPointerException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return nb;
    }

    /**
     * Get the total number of EJBs in a server
     * @param serverName the server name
     * @param domainName the domain name
     * @return map with the number of EJBs of different types where the key is the JSR77 type name
     */
    public static Map getTotalEJB(final String domainName, final String serverName) {
        HashMap<String, Integer> table = new HashMap<String, Integer>();
        int nbStatefulSessionBean = 0;
        int nbStatelessSessionBean = 0;
        int nbEntityBean = 0;
        int nbMessageDrivenBean = 0;
        ObjectName moduleOns = J2eeObjectName.getEJBModules(domainName, serverName);
        Iterator it = null;
        synchronized (s_Synchro) {
            it = JonasManagementRepr.queryNames(moduleOns, serverName).iterator();
        }
        while (it.hasNext()) {
            ObjectName moduleOn = (ObjectName) it.next();
            Map moduleTable = getTotalEJB(moduleOn);
            nbStatefulSessionBean = nbStatefulSessionBean + ((Integer) moduleTable.get("StatefulSessionBean")).intValue();
            nbStatelessSessionBean = nbStatelessSessionBean + ((Integer) moduleTable.get("StatelessSessionBean")).intValue();
            nbEntityBean = nbEntityBean + ((Integer) moduleTable.get("EntityBean")).intValue();
            nbMessageDrivenBean = nbMessageDrivenBean + ((Integer) moduleTable.get("MessageDrivenBean")).intValue();
        }
        table.put("StatefulSessionBean", nbStatefulSessionBean);
        table.put("StatelessSessionBean", nbStatelessSessionBean);
        table.put("EntityBean", nbEntityBean);
        table.put("MessageDrivenBean", nbMessageDrivenBean);
        return table;
    }

    /**
     * Get the total number of EJBs in a EJBModule
     * @param moduleOn the EJBModule's ObjectName
     * @return map with the number of EJBs of different types where the key is the JSR77 type name
     */
    public static Map getTotalEJB(final ObjectName moduleOn) {
        HashMap<String, Integer> table = new HashMap<String, Integer>();
        int nbStatefulSessionBean = 0;
        int nbStatelessSessionBean = 0;
        int nbEntityBean = 0;
        int nbMessageDrivenBean = 0;
        String serverName = moduleOn.getKeyProperty("J2EEServer");
        String[] ejbs = (String[]) JonasManagementRepr.getAttribute(moduleOn, "ejbs", serverName);
        for (int i = 0; i < ejbs.length; i++) {
            String ejbON = ejbs[i];
            try {
                ObjectName ejbOn = ObjectName.getInstance(ejbON);
                String ejbType = ejbOn.getKeyProperty("j2eeType");
                if ("StatefulSessionBean".equals(ejbType)) {
                    nbStatefulSessionBean++;
                } else if ("StatelessSessionBean".equals(ejbType)) {
                    nbStatelessSessionBean++;
                } else if ("EntityBean".equals(ejbType)) {
                    nbEntityBean++;
                } else if ("MessageDrivenBean".equals(ejbType)) {
                    nbMessageDrivenBean++;
                }
            } catch (MalformedObjectNameException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NullPointerException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        table.put("StatefulSessionBean", nbStatefulSessionBean);
        table.put("StatelessSessionBean", nbStatelessSessionBean);
        table.put("EntityBean", nbEntityBean);
        table.put("MessageDrivenBean", nbMessageDrivenBean);
        return table;
    }
}
