/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2008 Bull S.A.
 * 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.lib.management.extensions.manager;

import java.io.Serializable;
import java.util.List;

import org.ow2.jonas.lib.management.extensions.cluster.ClusterManagement;
import org.ow2.jonas.lib.management.extensions.clusterdaemon.ClusterdaemonManagement;
import org.ow2.jonas.lib.management.extensions.domain.DomainManagement;
import org.ow2.jonas.lib.management.extensions.server.ServerManagement;
import org.ow2.jonas.lib.management.extensions.server.ServerMonitoring;
import org.ow2.jonas.management.extensions.cluster.api.ICluster;
import org.ow2.jonas.management.extensions.clusterdaemon.api.IClusterdaemon;
import org.ow2.jonas.management.extensions.domain.api.IDomain;
import org.ow2.jonas.management.extensions.server.api.IServer;
import org.ow2.jonas.management.extensions.server.api.IServerManagement;

/**
 * Implements singleton for all management operations in JOnAS.
 * @author danesa
 * @author Oualaa Hani
 */
public final class ManagementEntryPoint implements IDomain, IServer, IClusterdaemon, ICluster, Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    /**
     * The ManagementEntryPoint singleton for management tools.
     */
    private static ManagementEntryPoint unique = null;

    /**
     * The IDomain Interface for DomainManagement implementation.
     */
    private static IDomain domainManagement = null;
    private static IServer serverMonitor = null;
    private static IServerManagement serverManagement = null;
    private static IClusterdaemon clusterdaemonManagement = null;
    private static ICluster clusterManagement = null;

    /**
     * @return ManagementEntryPoint singleton.
     */
    public static synchronized ManagementEntryPoint getInstance() {
        if(unique == null) {
            unique = new ManagementEntryPoint();
        }
        return unique;
    }

    /**
     * Constructor.
     */
    private ManagementEntryPoint() {
        domainManagement = new DomainManagement();
        serverMonitor = new ServerMonitoring();
        serverManagement = new ServerManagement();
        clusterdaemonManagement = new ClusterdaemonManagement();
        clusterManagement = new ClusterManagement();
    }

    // --------------------------------------------------
    // Domain management operations.
    // --------------------------------------------------

    /**
     * @return the current domain name.
     */
    public String getDomainName() {
        return domainManagement.getDomainName();
    }

    /**
     * @return the current server name.
     */
    public String getServerName() {
        return domainManagement.getServerName();
    }

    /**
     * @return the current server's host.
     */
    public String getServerHost() {
        return domainManagement.getServerHost();
    }

    /**
     * @return the current server's port if the web service activated.
     */
    public String getServerPort() {
        return domainManagement.getServerPort();
    }

    /**
     * Return True if the managed server is a master.
     * @param serverName managed server name
     * @return the "master" attribute of the corresponding J2EEDomain MBean
     */
    public boolean isMaster(final String serverName) {
        //Exception "ManagementException" if serverName doesn't exist
        return domainManagement.isMaster(serverName);
    }

    /**
     * Return True if the current server is a master.
     * @return the "master" attribute of the current J2EEDomain MBean
     */
    public boolean isMaster() {
        return domainManagement.isMaster();
    }

    /**
     * Return the server names that are belonging to the domain.
     * @return the server names that are belonging to the domain
     */
    public String[] getServerNames() {
        return domainManagement.getServerNames();
    }

    /**
     * @return the names of clusters in the domain.
     */
    public String[] getClustersNames() {
        return domainManagement.getClustersNames();
    }

    /**
     * @return the names of clusterDaemons in the domain.
     */
    public String[] getClusterDaemonNames() {
        return domainManagement.getClusterDaemonNames();
    }

    /**
     * Return the clusters in the domain. A cluster in the domain has associated a cluster MBean having
     * in its ObjectName a key property 'type' with values in {LogicalCluster, TomcatCluster, JkCluster, EjbHa}
     * @return the OBJECT_NAMES of the Cluster MBeans.
     */
    public String[] getClusters() {
        return domainManagement.getClusters();
    }

    /**
     * Return the clusterDaemons in the domain. A clusterDaemon in the domain has associated a cluster daemon MBean having
     * in its ObjectName a key property 'type' with value equal to 'ClusterDaemon'.
     * @return the OBJECT_NAMES of the Cluster Daemon MBeans.
     */
    public String[] getclusterDaemons() {
        return domainManagement.getclusterDaemons();
    }

    /**
     * Add a new server in the domain.
     * @param serverName the server's name.
     * @param connector the server's connector it can be JRMP, IRMI or IIOP.
     * @param userName the user of the new server.
     * @param password the password of the new server.
     * @param clusterDaemon the name of clusterDaemon if this server will take part of clusterDaemon.
     */
    public void addServer(final String serverName, final String serverURL, final String userName, final String password, final String clusterdaemon) {
        domainManagement.addServer(serverName, serverURL, userName, password, clusterdaemon);
    }

    /**
     * Remove a list of servers from the domain.
     * @param serversToRemove the list of servers to remove.
     */
    public void removeServers (final String[] serversToRemove){
        domainManagement.removeServers(serversToRemove);
    }

    /**
     * Add a new cluster in the domain.
     * @param clusterName the new cluster's name.
     */
    public void addCluster(final String clusterName){
        domainManagement.addCluster(clusterName);
    }

    /**
     * Return the state of a server in the domain.
     * @param serverName the server's name
     * @return the state of a server in the domain
     */
    public String getServerState(final String serverName) {
        return domainManagement.getServerState(serverName);
    }

    /**
     * Start the server.
     * @param serverName the name of the server to start
     */
    public void startServer(final String serverName){
        domainManagement.startServer(serverName);
    }

    /**
     * Stop the server.
     * @param serverName the name of the server to stop
     */
    public void stopServer(final String serverName){
        domainManagement.stopServer(serverName);
    }

    /**
     * Halt the server.
     * @param serverName the name of the server to halt
     */
    public void haltServer(final String serverName){
        domainManagement.haltServer(serverName);
    }

    /**
     * Return the clusterDaemon of a server in the domain.
     * @param serverName the server's name
     * @return the name of the server's cluster daemon
     */
    public String getServerClusterdaemon(final String serverName) {
        return domainManagement.getServerClusterdaemon(serverName);
    }

    /**
     * Return the state of a cluster in the domain.
     * @param clusterName the cluster's name
     * @return the state of a cluster in the domain
     */
    public String getClusterState(final String clusterName) {
        return domainManagement.getClusterState(clusterName);
    }

    /**
     * Return the type of a cluster in the current domain.
     * @param clusterName the cluster's name
     * @return the result of the getClusterType operation
     */
    public String getClusterType(final String clusterName) {
        return domainManagement.getClusterType(clusterName);
    }

    /**
     * @param clusterName the cluster name
     * @return the server names that are belonging to a cluster
     */
    public String[] getServerNames(final String clusterName) {
        return domainManagement.getServerNames(clusterName);
    }

    // --------------------------------------------------
    // Server management operations.
    // --------------------------------------------------

    /**
     * Get the memory used by a server in the domain.
     * @param server the server's name.
     * @return the used memory
     */
    public long getCurrentUsedMemory(final String server) {
        return serverMonitor.getCurrentUsedMemory(server);
    }

    /**
     * Get the version of a server in the domain.
     * @param server the server's name.
     * @return the server's version
     */
    public String getServerVersion(final String server) {
        return serverMonitor.getServerVersion(server);
    }

    /**
     * Get the number of threads used by a server in the domain.
     * @param server the server's name.
     * @return the number of threads
     */
    public int getAllThreadsCount(final String server) {
        return serverMonitor.getAllThreadsCount(server);
    }

    /**
     * Get the total memory of the server in the domain.
     * @param server the server's name.
     * @return the total memory
     */
    public Long getCurrentTotalMemory(final String server) {
        return serverMonitor.getCurrentTotalMemory(server);
    }

    /**
     * Get the JMX connection URL of the server.
     * @param server the server's name.
     * @return the JMX connection URL of the server
     */
    public String getConnectionUrl(final String server) {
        return serverMonitor.getConnectionUrl(server);
    }

    /**
     * Get the JVM vendor.
     * @param server the server's name.
     * @return the JVM vendor
     */
    public String getJavaVendor(final String server) {
        return serverMonitor.getJavaVendor(server);
    }

    /**
     * Get the java version.
     * @param server the server's name.
     * @return the java version
     */
    public String getJavaVersion(final String server) {
        return serverMonitor.getJavaVersion(server);
    }

    /**
     * Get the the protocols used bye the server.
     * @param server the server's name.
     * @return the protocols used bye the server
     */
    public String getProtocols(final String server) {
        return serverMonitor.getProtocols(server);
    }

    /**
     * @return total begun transactions.
     * @param server Server name
     */
    public int getTotalBegunTransactions(final String server){
        return serverMonitor.getTotalBegunTransactions(server);
    }

    /**
     * @return total commited transactions.
     * @param server Server name
     */
    public int getTotalCommittedTransactions(final String server) {
        return serverMonitor.getTotalCommittedTransactions(server);
    }

    /**
     * @return total expired transactions.
     * @param server Server name
     */
    public int getTotalExpiredTransactions(final String server) {
        return serverMonitor.getTotalExpiredTransactions(server);
    }

    /**
     * @return total global transactions.
     * @param server Server name
     */
    public int getTotalRolledbackTransactions(final String server) {
        return serverMonitor.getTotalRolledbackTransactions(server);
    }

    /**
     * @return total current transactions.
     * @param server Server name
     */
    public int getTotalCurrentTransactions(final String server) {
        return serverMonitor.getTotalCurrentTransactions(server);
    }

    /**
     * @return bytes received by connector tomcat.
     * @param server Server name
     */
    public long getBytesReceivedByConnectorTomcat(final String server) {
        return serverMonitor.getBytesReceivedByConnectorTomcat(server);
    }

    /**
     * @return bytes sent by connector tomcat.
     * @param server Server name
     */
    public long getBytesSentByConnectorTomcat(final String server) {
        return serverMonitor.getBytesSentByConnectorTomcat(server);
    }

    /**
     * @return current threads busy by connector tomcat.
     * @param server Server name
     */
    public int getCurrentThreadBusyByConnectorTomcat(final String server) {
        return serverMonitor.getCurrentThreadBusyByConnectorTomcat(server);
    }

    /**
     * @return current threads busy by connector tomcat.
     * @param server Server name
     */
    public int getCurrentThreadCountByConnectorTomcat(final String server) {
        return serverMonitor.getCurrentThreadCountByConnectorTomcat(server);
    }

    /**
     * @return error count by connector tomcat.
     * @param server Server name
     */
    public int getErrorCountByConnectorTomcat(final String server) {
        return serverMonitor.getErrorCountByConnectorTomcat(server);
    }

    /**
     * @return the max threads by connector tomcat.
     * @param server Server name
     */
    public int getMaxThreadsByConnectorTomcat(final String server) {
        return serverMonitor.getMaxThreadsByConnectorTomcat(server);
    }

    /**
     * @return processing time by connector tomcat.
     * @param server Server name
     */
    public long getProcessingTimeByConnectorTomcat(final String server) {
        return serverMonitor.getProcessingTimeByConnectorTomcat(server);
    }

    /**
     * @return request count by connector tomcat.
     * @param server Server name
     */
    public int getRequestCountByConnectorTomcat(final String server) {
        return serverMonitor.getRequestCountByConnectorTomcat(server);
    }

    /**
     * @return current number of EJB.
     * @param server Server name
     */
    public int getCurrentNumberOfEJB(final String server) {
        return serverMonitor.getCurrentNumberOfEJB(server);
    }

    /**
     * @return current number of Entity bean.
     * @param server Server name
     */
    public int getCurrentNumberOfEntityBean(final String server) {
        return serverMonitor.getCurrentNumberOfEntityBean(server);
    }

    /**
     * @return current number of mbean.
     * @param server Server name
     */
    public int getCurrentNumberOfMDB(final String server) {
        return serverMonitor.getCurrentNumberOfMDB(server);
    }

    /**
     * @return current number of state full bean.
     * @param server Server name
     */
    public int getCurrentNumberOfSBF(final String server) {
        return serverMonitor.getCurrentNumberOfSBF(server);
    }

    /**
     * @return current number of state less bean.
     * @param server Server name
     */
    public int getCurrentNumberOfSBL(final String server) {
        return serverMonitor.getCurrentNumberOfSBL(server);
    }

    // --------------------------------------------------
    // cluster daemon management operations.
    // --------------------------------------------------
    /**
     * @param clusterdaemonName name
     * @return list of servers controlled by a cluster daemon
     */
    public String[] getControlledServersNames(final String clusterdaemonName) {

        return clusterdaemonManagement.getControlledServersNames(clusterdaemonName);
    }

    /**
     * @param clusterdaemonName name of the cluster daemon to manage.
     * @return true if the cluster daemon is in RUNNING state, false otherwise
     */
    public boolean isRunning(final String clusterdaemonName) {
        return clusterdaemonManagement.isRunning(clusterdaemonName);
    }

    /**
     * @return the state of a cluster daemon in the domain
     * @param clusterdaemonName name of the cluster daemon to manage
     */
    public String getClusterdaemonState(final String clusterdaemonName) {
        return clusterdaemonManagement.getClusterdaemonState(clusterdaemonName);
    }
    // --------------------------------------------------
    // cluster management operations.
    // --------------------------------------------------
    /**
     * start all servers in the cluster.
     * @param clusterName
     */
    public void startAllServers(final String clusterName){
        clusterManagement.startAllServers(clusterName);
    }

    /**
     * stop all servers in the cluster.
     * @param clusterName
     */
    public void stopAllServers(final String clusterName) {
        clusterManagement.stopAllServers(clusterName);
    }

    /**
     * @param clusterName
     * @return the multicast address
     */
    public String getMcastAddr(final String clusterName) {
        return clusterManagement.getMcastAddr(clusterName);
    }

    /**
     * @param clusterName
     * @return the multicast port
     */
    public int getMcastPort(final String clusterName) {
        return clusterManagement.getMcastPort(clusterName);
    }

    /**
     * @param clusterName
     * @return the delay used by clients to update their cluster view
     */
    public int getDelayToRefresh(final String clusterName){
        return clusterManagement.getDelayToRefresh(clusterName);
    }

    /**
     * Get the name of the servers in the domain except the ones that are belonging to this cluster.
     * @param clusterName the cluster name
     * @return name of the servers that can be attached to the cluster
     */
     public String[] getServersNotInCluster(final String clusterName) {
         return domainManagement.getServersNotInCluster(clusterName);
     }

     /**
      * @return the current server threads information.
      * @param serverName Server name
      * @throws Exception when operation invocation fails
      */
     public List<List<String>> getServerThreadsInformation(final String serverName) throws Exception {
         return serverManagement.getServerThreadsInformation(serverName);
     }

     /**
      * @return the current server threads information.
      * @param jmxUrl
      * @param username
      * @param password
      * @throws Exception when operation invocation fails
      */
     public List<List<String>> getServerThreadsInformation(final String jmxUrl, final String username, final String password) throws Exception {
         return serverManagement.getServerThreadsInformation(jmxUrl, username, password);
     }
}
