/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2006 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.domain.cluster.tomcat;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.ow2.jonas.lib.management.domain.cluster.ClusterMember;
import org.ow2.jonas.lib.management.domain.proxy.server.ServerProxy;

import org.objectweb.util.monolog.api.BasicLevel;


/**
 * A TomcatClusterMember represents a JOnAS server using web container Tomcat which is a memeber of a
 * Tomcat cluster for session replication.
 * @author Philippe Durieux
 * @author Adriana Danes
 */
public class TomcatClusterMember extends ClusterMember implements TomcatClusterMemberMBean {

    // Tomcat ClusterReceiver MBean attributes
    // -------------------------------------
    // Receiver Info
    /**
     * tcp listener address
     */
    private String tcpListenAddress = null;
    /**
     * tcp listener port
     */
    private int tcpListenPort;
    /**
     * data received compressed
     */
    private boolean compress;
    /**
     * create received processing time stats
     */
    private boolean doReceivedProcessingStats;
    /**
     * Class version info (ClusterReceiver.info)
     */
    private String receiverInfo;
    /**
     * send ack after data received
     */
    private boolean sendAck;
    /**
     * tcp listener Selector timeout
     */
    private long tcpSelectorTimeout;

    // Receiver Stats
    /**
     * received processing time / nrOfRequests
     */
    private double avgReceivedProcessingTime;
    /**
     * received processing time / nrOfRequests
     * - think should be double
     */
    //private long avgTotalReceivedBytes;
    /**
     * maximal received processing time
     */
    private long maxReceivedProcessingTime;
    /**
     * minimal received processing time
     */
    private long minReceivedProcessingTime;
    /**
     * number of messages received from other nodes
     */
    private long nrOfMsgsReceived;
    /**
     * received processing time
     */
    private long receivedProcessingTime;
    /**
     * total time message send time
     */
    private long receivedTime;
    /**
     * number of tcp listener worker threads
     */
    private int tcpThreadCount;
    /**
     * number of bytes received
     */
    private long totalReceivedBytes;
    /**
     * is port really started
     */
    private boolean doListen;
    // Sender info
    /* all the possible attributes:
    "ackTimeout", "autoConnect", "avgProcessingTime", "doTransmitterProcessingStats",
    "failureCounter", "info", "maxProcessingTime", "minProcessingTime",
    "nrOfRequests", "processingTime", "replicationMode",
    "totalBytes", "waitForAck"
    */
    // selected configuration attributes
    /**
     * Class version info (ClusterSender.info)
     */
    private String senderInfo;
    /**
     * acknowledge timeout
     */
    private long ackTimeout;
    /**
     * is sender disabled, fork a new socket
     */
    private boolean autoConnect;
    /**
     * create processing time stats
     */
    private boolean doTransmitterProcessingStats;
    /**
     * replication mode (synchnous,pooled.asynchnous,fastasyncqueue)
     */
    private String replicationMode;
    /**
     * Wait for ack after data send
     */
    private boolean waitForAck;

    // General info
    /**
     * tomcat cluster member's host name (virtual host)
     */
    private String hostName;
    /**
     * JOnAS management domain name
     */
    private String domainName;

    /**
     * Constructor
     * @param name memberName generated by the TomcatCluster
     * @param hostName the virtual host name
     * @param proxy the member's proxy
     */
    public TomcatClusterMember(String name, String hostName, ServerProxy proxy) {
        super(name, proxy);
        this.hostName = hostName;
        this.domainName = proxy.getDomain();
    }

    /**
     * Set attributes with values from TomcatSender
     * and TomcatReceiver MBeans
     */
    public void setInfo() {
        // Attributes for TomcatReceiver
        ObjectName crOn = null;
        try {
            // CatalinaObjectName
            crOn = ObjectName.getInstance(domainName + ":type=ClusterMembership,host=" + hostName);
        } catch (MalformedObjectNameException e) {
            logger.log(BasicLevel.WARN, e);
            return;
        }
        String[] attNames = new String[] {
                "avgReceivedProcessingTime", "compress", "doReceivedProcessingStats",
                "maxReceivedProcessingTime", "minReceivedProcessingTime", "nrOfMsgsReceived",
                "receivedProcessingTime", "receivedTime", "info",
                "sendAck", "tcpListenAddress", "tcpListenPort", "tcpSelectorTimeout",
                "tcpThreadCount", "totalReceivedBytes"
        };
        AttributeList attList = proxy.getAttributes(crOn, attNames);
        for (int i = 0; i < attList.size(); i++) {
            Attribute att = (Attribute) attList.get(i);
            String attName = att.getName();
            Object attValue = att.getValue();
            if ("avgReceivedProcessingTime".equals(attName)) {
                setAvgReceivedProcessingTime(((Double) attValue).doubleValue());
            }
            if ("compress".equals(attName)) {
                setCompress(((Boolean) attValue).booleanValue());
            }
            if ("doReceivedProcessingStats".equals(attName)) {
                setDoReceivedProcessingStats(((Boolean) attValue).booleanValue());
            }
            if ("maxReceivedProcessingTime".equals(attName)) {
                setMaxReceivedProcessingTime(((Long) attValue).longValue());
            }
            if ("minReceivedProcessingTime".equals(attName)) {
                setMinReceivedProcessingTime(((Long) attValue).longValue());
            }
            if ("nrOfMsgsReceived".equals(attName)) {
                setNrOfMsgsReceived(((Long) attValue).longValue());
            }
            if ("receivedProcessingTime".equals(attName)) {
                setReceivedProcessingTime(((Long) attValue).longValue());
            }
            if ("receivedTime".equals(attName)) {
                setReceivedTime(((Long) attValue).longValue());
            }
            if ("info".equals(attName)) {
                setReceiverInfo((String) attValue);
            }
            if ("sendAck".equals(attName)) {
                setSendAck(((Boolean) attValue).booleanValue());
            }
            if ("tcpListenAddress".equals(attName)) {
                setTcpListenAddress((String) attValue);
            }
            if ("tcpListenPort".equals(attName)) {
                setTcpListenPort(((Integer) attValue).intValue());
            }
            if ("tcpSelectorTimeout".equals(attName)) {
                setTcpSelectorTimeout(((Long) attValue).longValue());
            }
            if ("tcpThreadCount".equals(attName)) {
                int threadCount = ((Integer) attValue).intValue();
                //System.out.println(">>>> threadCount = " + threadCount);
                setTcpThreadCount(threadCount);
            }
            if ("totalReceivedBytes".equals(attName)) {
                setTotalReceivedBytes(((Long) attValue).longValue());
            }
        }
        // Attributes from TomcatSender
        ObjectName csOn = null;
        try {
            // CatalinaObjectName
            csOn = ObjectName.getInstance(domainName + ":type=ClusterSender,host=" + hostName);
        } catch (MalformedObjectNameException e) {
            logger.log(BasicLevel.WARN, e);
            return;
        }
        attNames = new String[] {
                "ackTimeout", "autoConnect", "avgProcessingTime", "doTransmitterProcessingStats",
                "failureCounter", "info", "maxProcessingTime", "minProcessingTime",
                "nrOfRequests", "processingTime", "replicationMode",
                "totalBytes", "waitForAck"
        };
        attList = proxy.getAttributes(csOn, attNames);
        for (int i = 0; i < attList.size(); i++) {
            Attribute att = (Attribute) attList.get(i);
            String attName = att.getName();
            Object attValue = att.getValue();
            if ("ackTimeout".equals(attName)) {
                setAckTimeout(((Long) attValue).longValue());
            }
            if ("autoConnect".equals(attName)) {
                setAutoConnect(((Boolean) attValue).booleanValue());
            }
            if ("doTransmitterProcessingStats".equals(attName)) {
                setDoTransmitterProcessingStats(((Boolean) attValue).booleanValue());
            }
            if ("info".equals(attName)) {
                setSenderInfo((String) attValue);
            }
            if ("replicationMode".equals(attName)) {
                setReplicationMode((String) attValue);
            }
            if ("waitForAck".equals(attName)) {
                setWaitForAck(((Boolean) attValue).booleanValue());
            }
        }
    }
    /**
     * @return tcp listener address
     */
    public String getTcpListenAddress() {
        return tcpListenAddress;
    }
    public void setTcpListenAddress(String tcpListenAddress) {
        this.tcpListenAddress = tcpListenAddress;
    }

    /**
    *
    * @return tcp listener port
    */
    public int getTcpListenPort() {
        return tcpListenPort;
    }
    public void setTcpListenPort(int tcpListenPort) {
        this.tcpListenPort = tcpListenPort;
    }


    public boolean isCompress() {
        return compress;
    }


    public boolean isDoReceivedProcessingStats() {
        return doReceivedProcessingStats;
    }


    public String getReceiverInfo() {
        return receiverInfo;
    }


    public boolean isSendAck() {
        return sendAck;
    }


    public long getTcpSelectorTimeout() {
        return tcpSelectorTimeout;
    }


    public String getHostName() {
        return hostName;
    }


    public double getAvgReceivedProcessingTime() {
        return avgReceivedProcessingTime;
    }


    public long getMaxReceivedProcessingTime() {
        return maxReceivedProcessingTime;
    }


    public void setAvgReceivedProcessingTime(double avgReceivedProcessingTime) {
        this.avgReceivedProcessingTime = avgReceivedProcessingTime;
    }


    public void setCompress(boolean compress) {
        this.compress = compress;
    }


    public void setDoListen(boolean doListen) {
        this.doListen = doListen;
    }


    public void setDoReceivedProcessingStats(boolean doReceivedProcessingStats) {
        this.doReceivedProcessingStats = doReceivedProcessingStats;
    }


    public void setMaxReceivedProcessingTime(long maxReceivedProcessingTime) {
        this.maxReceivedProcessingTime = maxReceivedProcessingTime;
    }


    public void setMinReceivedProcessingTime(long minReceivedProcessingTime) {
        this.minReceivedProcessingTime = minReceivedProcessingTime;
    }


    public void setNrOfMsgsReceived(long nrOfMsgsReceived) {
        this.nrOfMsgsReceived = nrOfMsgsReceived;
    }


    public void setReceivedProcessingTime(long receivedProcessingTime) {
        this.receivedProcessingTime = receivedProcessingTime;
    }


    public void setReceivedTime(long receivedTime) {
        this.receivedTime = receivedTime;
    }


    public void setReceiverInfo(String receiverInfo) {
        this.receiverInfo = receiverInfo;
    }


    public void setSendAck(boolean sendAck) {
        this.sendAck = sendAck;
    }


    public void setTcpSelectorTimeout(long tcpSelectorTimeout) {
        this.tcpSelectorTimeout = tcpSelectorTimeout;
    }


    public void setTcpThreadCount(int tcpThreadCount) {
        this.tcpThreadCount = tcpThreadCount;
    }


    public void setTotalReceivedBytes(long totalReceivedBytes) {
        this.totalReceivedBytes = totalReceivedBytes;
    }


    public long getMinReceivedProcessingTime() {
        return minReceivedProcessingTime;
    }


    public long getNrOfMsgsReceived() {
        return nrOfMsgsReceived;
    }


    public long getReceivedProcessingTime() {
        return receivedProcessingTime;
    }


    public long getReceivedTime() {
        return receivedTime;
    }


    public boolean isDoListen() {
        return doListen;
    }


    public int getTcpThreadCount() {
        return tcpThreadCount;
    }


    public long getTotalReceivedBytes() {
        return totalReceivedBytes;
    }


    public String getSenderInfo() {
        return senderInfo;
    }


    public void setSenderInfo(String senderInfo) {
        this.senderInfo = senderInfo;
    }

    public long getAckTimeout() {
        return ackTimeout;
    }


    public void setAckTimeout(long ackTimeout) {
        this.ackTimeout = ackTimeout;
    }


    public boolean isAutoConnect() {
        return autoConnect;
    }


    public void setAutoConnect(boolean autoConnect) {
        this.autoConnect = autoConnect;
    }


    public boolean isDoTransmitterProcessingStats() {
        return doTransmitterProcessingStats;
    }


    public void setDoTransmitterProcessingStats(boolean doTransmitterProcessingStats) {
        this.doTransmitterProcessingStats = doTransmitterProcessingStats;
    }


    public String getReplicationMode() {
        return replicationMode;
    }


    public void setReplicationMode(String replicationMode) {
        this.replicationMode = replicationMode;
    }


    public boolean isWaitForAck() {
        return waitForAck;
    }


    public void setWaitForAck(boolean waitForAck) {
        this.waitForAck = waitForAck;
    }
}