/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * This software is the proprietary information of Sun Microsystems, Inc.
 * Use is subject to license terms.
 * 
 * Copyright 2004 Sun Microsystems, Inc.  Tous droits r?serv?s.
 * Ce logiciel est propri?t? de Sun Microsystems, Inc.
 * Distribu? par des licences qui en restreignent l'utilisation.
 *
 * ident        "@(#)MSG_SRVImpl.java 1.14     04/07/28 SMI"
 *
 */

package com.sun.mfwk.examples.msgCP;


// java imports
//

import java.util.*;
import java.io.*;
import java.net.UnknownHostException;
import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
import java.util.logging.Logger;


// JDMK import
import com.sun.jdmk.comm.*;
import com.sun.jdmk.*;

// JMX RI imports
import javax.management.*;
import javax.management.remote.*;
import javax.management.remote.jmxmp.*;

// JESMA transaction API
import com.sun.mfwk.trans.*;
import com.sun.mfwk.util.instrum.*;
import com.sun.mfwk.discovery.*;
import com.sun.mfwk.util.log.*;


public class MSG_SRVImpl extends UnicastRemoteObject implements MSG_SRV {


    private MBeanServer mbs = null;
    private MfTransactionFactory tranFactory ;
    private MfTransactionDefinition LOGTranDef, MSGTranDef;
    private MfTransactionMetrics LOGServiceMetrics, MSGServiceMetrics;
    private MfStatus MSG_SRVStatusMetrics;
    private MfInstrumManagement MSG_SRVImgt;
    private MfInstrumConfig MSG_SRVCfg;

    private boolean isDegraded = false;
    private Integer port = new Integer(0);
    private String instanceName = "";
    private String instanceId = "1099"; // we use the rmi port to identify the instance
    private File outputFile = null;
    private FileWriter out = null;

    private static String fileName = File.separator + "tmp" + File.separator + "msg.txt";

    private static final String USAGE = "java com.sun.mfwk.examples.msgCP.MSG_SRVImpl [-p <port>]";

    private Logger logger = null;

    /*
    ** Constructor
    */
    public MSG_SRVImpl() throws RemoteException {
	super();
	try {
		MfLogService logSrv = new MfLogService("MsgSrv");
		logger = MfLogService.getLogger("MSG_SRV");
		outputFile = new File(fileName);
		outputFile.delete();
		outputFile.createNewFile();
		out = new FileWriter(outputFile);
		out.write(new String(">>>> New LOG_SRV : instance MSG_SRV_instance" + "\n"));
		out.flush();
	} catch (IOException e) {
		logger.info("Cannot create new file /tmp/msg.txt to log messages. We run in DEGRADED state.\n");
		isDegraded = true;
	}

    }

    private String parseargs(String[] args) {
	int index = 0;
	String port = "";
	String serviceName = "";
	if (args.length > 2) {
		System.out.println(USAGE);
		System.exit(1);
	}
	while (index < args.length) {
		if (args[index].equals("-p")) {
			if (++index == args.length) {
				System.err.println("Missing port number\n");
				System.err.println(USAGE);
				System.exit(1);
			}
			port = args[index];
                        instanceId = port.toString();
		} else {
			System.err.println("Unrecognized option\n");
			System.err.println(USAGE);
			System.exit(1);
		}
		index++;
	}
	if (port.length() == 0) {
		serviceName = "//localhost/MSG_SRV";
	} else {
		serviceName = "//localhost:" + port.toString() + "/MSG_SRV";
	}
	return serviceName;
    }


    public static void main(String[] args) {
        //if (System.getSecurityManager() == null) {
        //             System.setSecurityManager(new RMISecurityManager());
        //}

        try {
                MSG_SRVImpl myMSG_SRV = new MSG_SRVImpl();
		String name = myMSG_SRV.parseargs(args);
                Naming.rebind(name, myMSG_SRV);
		// Initialization of monitoring
		myMSG_SRV.initMonitoring();
        } catch (Exception e) {
                System.err.println("MSG_SRV RMI binding exception: " +
                                  e.getMessage());
		System.exit(1);
        }

    }


    public void LOG(String message) throws RemoteException {

	  // Define the MfTransaction instance (start/stop mode)
          MfTransaction tran = tranFactory.newTransaction(LOGTranDef, null);

         // Start the transaction
          tran.start();

	 // print the message to file
	 try {
		 MSG_SRVImpl.sleep();
		 if (!isDegraded) {
				 out.write(message);
				 out.flush();
		 } else {
			 System.out.println(message);
		 }
	 } catch (Exception e) {
		 tran.stop(MfConstants.STATUS_FAILED);
	 }

	 tran.stop(MfConstants.STATUS_GOOD);

    }

    public void MSG(String message) throws RemoteException {

	  // Define the MfTransaction instance (start/stop mode)
          MfTransaction tran = tranFactory.newTransaction(LOGTranDef, null);

         // Start the transaction
          tran.start();

	 // print the message to file AND stdout
	 try {
		 MSG_SRVImpl.sleep();
		 if (!isDegraded) {
			 out.write(message);
			 out.flush();
		 }
	 } catch (Exception e) {
		 tran.stop(MfConstants.STATUS_FAILED);
	 }
	 System.out.println(message);
	 tran.stop(MfConstants.STATUS_GOOD);

    }


    public void initMonitoring() {

        JMXServiceURL addr;

        // Parse system properties to check if LEVEL_TRACE and/or
	// LEVEL_DEBUG are set and enable the TRACE level accordingly
        try {
            TraceManager.parseTraceProperties();
        }
        catch (IOException e) {
            e.printStackTrace();
        }

	/*
        ** Create the MBean server
	*/
	mbs = MBeanServerFactory.createMBeanServer();

	/*
        ** Create JDMK HTML adaptor for debug
	*/
	HtmlAdaptorServer htmlAdaptor = new HtmlAdaptorServer(8084);
        try {
            ObjectName oName =
                new ObjectName("jmx", "type", "htmlAdaptor");
            mbs.registerMBean(htmlAdaptor, oName);
	    htmlAdaptor.start();
        } catch(Exception e) {
            e.printStackTrace();
        }
	// waiting to leave starting state...
        while (htmlAdaptor.getState() == CommunicatorServer.STARTING) {
	    logger.finest("sleeping on htmlAdaptor");
            sleep(500);
        }
        logger.finest("\nHTML protocol adaptor started on port "+ htmlAdaptor.getPort());

	/*
        ** Create JSR 160 JMXMP connector
	*/
	JMXConnectorServer cs = null;
	try {
	    JMXServiceURL url = new JMXServiceURL("jmxmp", null, 0);
	    cs = new JMXMPConnectorServer(url, null);
	    ObjectName csName =
		new ObjectName("jmx:type=cserver,name=jmxmpConnectorServer");
	    mbs.registerMBean(cs, csName);
	    cs.start();
	} catch (Exception e) {
	    e.printStackTrace();
	    System.exit(1);
	}

	logger.finest("\nJMXMP connector started.");
        addr = cs.getAddress();
	logger.finest("# URI is: "+addr);

	/*
	** Instanciate transaction factory
	*/

	tranFactory = new MfTransactionFactoryImpl();


	/*
	** Instanciate the MfStatus Metrics MBean for the STORE_SRV Application
	*/
        MSG_SRVStatusMetrics = new MfStatus();
        // Register it in the MBeanServer
        try {
            mbs.registerMBean(MSG_SRVStatusMetrics, MfObjectNameFactory.getStatusName());
        } catch (Exception e) {
            e.printStackTrace();
	}

	MSG_SRVStatusMetrics.setOperationalState(MfStatus.OPS_STARTING);
	MSG_SRVStatusMetrics.setOpsStateLastChange(java.lang.System.currentTimeMillis());

	/*
	** Instanciate the MfTransaction Metrics MBean for LOG Service
	*/
        MfTransactionMetrics LOGServiceMetrics = new MfTransactionMetrics();
        // Register it in the MBeanServer
        try {
            mbs.registerMBean(LOGServiceMetrics, MfObjectNameFactory.getTransactionMetricsName("LOG"));
        } catch (Exception e) {
            e.printStackTrace();
        }
	LOGServiceMetrics.setOperationalState(MfStatus.OPS_STARTING);
	LOGServiceMetrics.setOpsStateLastChange(java.lang.System.currentTimeMillis());

	/*
	** Instanciate the MfTransaction Metrics MBean for MSG Service
	*/
        MfTransactionMetrics MSGServiceMetrics = new MfTransactionMetrics();
        // Register it in the MBeanServer
        try {
            mbs.registerMBean(MSGServiceMetrics, MfObjectNameFactory.getTransactionMetricsName("MSG"));
        } catch (Exception e) {
            e.printStackTrace();
        }
	MSGServiceMetrics.setOperationalState(MfStatus.OPS_STARTING);
	MSGServiceMetrics.setOpsStateLastChange(java.lang.System.currentTimeMillis());

        /*
        ** Instanciate the Instrumentation Management MBean for the MSG_SRV
        */
        MSG_SRVImgt = new MfInstrumManagement();
        // Register it in the MBeanServer
        try {
            mbs.registerMBean(MSG_SRVImgt, MfObjectNameFactory.getInstrumManagementName());
        } catch (Exception e) {
            e.printStackTrace();
        }

        /*
        ** Instanciate the MfConfig Management MBean for the MSG_SRV and set its attributes
        */
        MSG_SRVCfg = new MfInstrumConfig();
        // Register it in the MBeanServer
        try {
            mbs.registerMBean(MSG_SRVCfg, MfObjectNameFactory.getInstrumConfigName());
	    MSG_SRVCfg.setAppRole("standalone server");
	    MSG_SRVCfg.setAppURLDescription("MSG_SRV URL Description");
	    MSG_SRVCfg.setAppDirectoryDN("MSG_SRV Directory DN");
        } catch (Exception e) {
            e.printStackTrace();
        }


        /*
        ** Define the MfTransaction types
        */
        LOGTranDef =
            tranFactory.newTransactionDefinition("CP LOG", "localhost://MSG_SRV/log", LOGServiceMetrics);

        MSGTranDef =
            tranFactory.newTransactionDefinition("CP MSG", "localhost://MSG_SRV/msg", MSGServiceMetrics);


	/*
	** Send Discovery multicast
	*/ 		
        instanceName = new String ("instance_" + instanceId);
	byte[] userData = new byte[]{'r','m','i',':','/','/','l','o','c','a','l','h','o','s','t','/','M','S','G','_','S','R','V'};
	try {
	    MfDiscoveryResponder testSdk = new MfDiscoveryResponder("MSG_SRV",this.instanceName,addr.toString(),userData);
	} catch (IOException e) {
            logger.info("Unexpected Exception while creating Discovery Responder...");
            e.printStackTrace();
	}


	MSG_SRVStatusMetrics.setOperationalState(MfStatus.OPS_RUNNING);
	MSG_SRVStatusMetrics.setOpsStateLastChange(java.lang.System.currentTimeMillis());
	MSG_SRVStatusMetrics.setRunningTime(java.lang.System.currentTimeMillis());
	MSGServiceMetrics.setOperationalState(MfStatus.OPS_RUNNING);
	MSGServiceMetrics.setOpsStateLastChange(java.lang.System.currentTimeMillis());
	MSGServiceMetrics.setRunningTime(java.lang.System.currentTimeMillis());
	LOGServiceMetrics.setOperationalState(MfStatus.OPS_RUNNING);
	LOGServiceMetrics.setOpsStateLastChange(java.lang.System.currentTimeMillis());
	LOGServiceMetrics.setRunningTime(java.lang.System.currentTimeMillis());
	if (isDegraded) {
		MSG_SRVStatusMetrics.setAvailabilityState(MfStatus.AVAIL_DEGRADED);
		MSG_SRVStatusMetrics.setDegradedTime(java.lang.System.currentTimeMillis());
		MSGServiceMetrics.setAvailabilityState(MfStatus.AVAIL_DEGRADED);
		MSGServiceMetrics.setDegradedTime(java.lang.System.currentTimeMillis());
		LOGServiceMetrics.setAvailabilityState(MfStatus.AVAIL_DEGRADED);
		LOGServiceMetrics.setDegradedTime(java.lang.System.currentTimeMillis());
	} else {
		MSG_SRVStatusMetrics.setAvailabilityState(MfStatus.AVAIL_NORMAL);
		MSGServiceMetrics.setAvailabilityState(MfStatus.AVAIL_NORMAL);
		LOGServiceMetrics.setAvailabilityState(MfStatus.AVAIL_NORMAL);
	}
	MSG_SRVStatusMetrics.setAvailStateLastChange(java.lang.System.currentTimeMillis());
	MSGServiceMetrics.setAvailStateLastChange(java.lang.System.currentTimeMillis());
	LOGServiceMetrics.setAvailStateLastChange(java.lang.System.currentTimeMillis());


    }


    private static void sleep(int t) {
		try {
			Thread.sleep(t);
		} catch (InterruptedException e) {
		    return;
		}
    }

    private static void sleep() {
		try {
			Thread.sleep((int)(Math.random() * 10));
		} catch (InterruptedException e) {
		    return;
		}
    }


}

