/*
 * 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        "@(#)STORE_SRVModule.java 1.42     04/09/30 SMI"
 *
 */


package com.sun.mfwk.examples.storeCP;

// J2SE
import java.util.logging.Logger;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.Date;

// JMX
import javax.management.ObjectName;
import javax.management.Attribute;
import javax.management.Query;
import javax.management.QueryExp;
import javax.management.NotificationListener;
import javax.management.Notification;
import javax.management.MBeanRegistrationException;
import javax.management.remote.JMXConnector;
import com.sun.jdmk.comm.*;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
// Cacao
import com.sun.cacao.DeploymentDescriptor;
import com.sun.cacao.Module;
import com.sun.cacao.ModuleMBean;

// CP
import com.sun.mfwk.util.log.MfLogService;
import com.sun.mfwk.cib.*;
import com.sun.mfwk.cib.sdk.util.CIBMBeansFactory;
import com.sun.mfwk.util.instrum.MfObjectNameFactory;

import com.sun.mfwk.discovery.MfDiscoveryInfo;
import javax.management.NotificationFilterSupport;

// Security
import com.sun.mfwk.security.factory.MfJMXConnectorFactory;

/**
 * The Store Server module
 *
 */
public class STORE_SRVModule extends Module implements NotificationListener {
    
    /* Tracing utility. */
    private static Logger logger =
    MfLogService.getLogger("storeSrv_module");
    private String prodName = "";
    private CIBProduct cp = null;
    private Map listOfAppliInstances = new HashMap();
    private CIBMBeansFactory cibFactory = null;
    ObjectName discoveryServiceObjectName = null;
    
    
    /**
     * Creates a new <code>STORE_SRVModule</code> instance.
     *
     */
    public STORE_SRVModule(DeploymentDescriptor descriptor) {
        
        super(descriptor);
        cibFactory = new CIBMBeansFactory((Module) this);
    }
    
    /**
     * Describe <code>start</code> method here.
     *
     */
    protected void start() {
        
        NotificationFilterSupport myFilter = new NotificationFilterSupport();
        logger.info("STORE_SRV module is starting");
        // Create and register CIBProduct Mbean
        logger.info("Create and register CIBProduct Mbean: STORE_SRV Product");
        try {
            cp = cibFactory.createCIBProduct( "STORE_SRV",
            "v1.0",
            "none",
            0,
            "SUN Microsystems");
            this.prodName="STORE_SRV";
            myFilter.enableType(this.prodName);
            try {
                discoveryServiceObjectName = new ObjectName("com.sun.mfwk.mfwk_module:type=mfDiscoveryService,name=mfDiscoveryService");
                getMbs().addNotificationListener(discoveryServiceObjectName, (NotificationListener) this, myFilter, null);
            } catch(Exception e) {
                logger.warning("cannot succeed in adding listener on  : " + e.getMessage());
            }
            
        } catch (Throwable e) {
            logger.warning("Caught Exception during creation of CIB Product : " + e.toString());
        }
    }
    
    
    
    public void handleNotification(Notification notification, Object handback) {
        
        CIBApplication appl1;
        CIBService srv1, srv2, srv3;
        CIBExternalResource extsrv1;
        CIBResource res1 ;
        boolean isSecured = false;
        
        try {
            
            logger.info("\n\t>> ComponentProductCIBModuleListener handles received notification :");
            String type = notification.getType();
            
            MfDiscoveryInfo receivedMsg = null;
            receivedMsg = (com.sun.mfwk.discovery.MfDiscoveryInfo) notification.getUserData();
            String userData = new String(receivedMsg.getUserData());

            logger.info("\tProduct: " + receivedMsg.getProduct());
            logger.info("\tApplicationInstance: " + receivedMsg.getProductInstance());
            logger.info("\tProductUri: " + receivedMsg.getUri());
            logger.info("\tProductTimeStamp: " + Long.toString(receivedMsg.getTimeStamp()));            
            logger.info("userData = " + userData);
            if (receivedMsg.getTimeStamp() > -1){
                logger.info("\tProductTimeStamp Date: " + (new Date(receivedMsg.getTimeStamp())).toString());
            }   
            
            //Checks if it is a known instance (can be restart of a known instance)
            if ( listOfAppliInstances.containsKey(receivedMsg.getProductInstance() )) {
                
                // The instance was already started
                // check if this message corresponds to a new start
                Long lastStart = (Long)listOfAppliInstances.get(receivedMsg.getProductInstance());
                Long startDate = new Long(receivedMsg.getTimeStamp());
                
                if (lastStart.longValue() >= startDate.longValue()) {
                    // This is a re-send of discovery message
                    // of an already registered appl
                    // nothing to do
                    return;
                }
                
                // otherwise, we will have to do some cleanup
                // to take into account the new connection
                
                logger.info("This is a restart of instance " +
                receivedMsg.getProductInstance());
                listOfAppliInstances.remove(receivedMsg.getProductInstance());
                cibFactory.removeCIBApplication(receivedMsg.getProductInstance());
                
            } // end if the instance was already started
                
            // If we are here, it means, either it is a new
            // instance, either it is an existing instance
            // that has been restarted (new timestamp).
            // in both case we rebuild all the cib stuff

            // Add the instance in the map
            listOfAppliInstances.put(receivedMsg.getProductInstance(), new Long(receivedMsg.getTimeStamp()));
            
            JMXConnector connector = null;
            if (userData.equals("secured")) {
                connector = MfJMXConnectorFactory.connect(new JMXServiceURL(receivedMsg.getUri()));
            } else {
                connector = JMXConnectorFactory.connect(new JMXServiceURL(receivedMsg.getUri()));
            }
            MBeanServerConnection connection = connector.getMBeanServerConnection();
            
            // ProviderHandler creation
            cibFactory.createCIBProviderHandler(connection);
            
            //Create and register CIBApplication MBean
            logger.info("Create and register CIBApplication  MBean : " + receivedMsg.getProductInstance());
            appl1 = cibFactory.newCIBApplication(receivedMsg.getProductInstance(), true, true, false);
            appl1.setDescription("this is one instance " + receivedMsg.getProductInstance() + " of the product " + receivedMsg.getProduct());
            
            //Create and register CIBService MBeans
            String serviceName1 = new String("SEARCH");
            logger.info("Create and register CIBService MBean " + serviceName1 );
            srv1 = cibFactory.newCIBApplicationService(serviceName1, appl1, true, true, false);
            
            String serviceName2 = new String("MODIFY");
            logger.info("Create and register CIBService MBean " + serviceName2 );
            srv2 = cibFactory.newCIBApplicationService(serviceName2, appl1, true, true, false);
            
            String serviceName3 = new String("REMOVE");
            logger.info("Create and register CIBService MBean " + serviceName3 );
            srv3 = cibFactory.newCIBApplicationService(serviceName3, appl1, true, true, false);
            
            //Create and register CIBExternalResource MBeans
            String externalResource1 = new String("MSG_SRV");
            logger.info("Create and register CIBExternalResource MBean " + externalResource1);
            extsrv1 = cibFactory.newCIBApplicationExternalResource(externalResource1, appl1, true, true, false);
            
            //Create and register CIBResource MBeans
            //One resource on application
            String resourceName1 = new String("STORE");
            logger.info("Create and register CIBResource MBean " + resourceName1);
            res1 = cibFactory.newCIBApplicationResource(resourceName1, appl1, true, true, false);
        } catch (Throwable e) {
            logger.warning("Caught Exception during creation of CIB : " + e.toString() + " message : " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    /**
     * Describe <code>stop</code> method here.
     *
     */
    protected void stop() {
        try {
            cibFactory.removeCIBProduct(this.prodName);
        } catch (Throwable e) {
            logger.warning("Caught Exception during removal of CIB objects : " + e.toString() + " message : " + e.getMessage());
            e.printStackTrace();
        }
	try {
	    	getMbs().removeNotificationListener(discoveryServiceObjectName, (NotificationListener) this);
	} catch (Throwable e) {
		logger.warning("Caught Exception during removal of listener : " + e.toString() + " message : " + e.getMessage());
		e.printStackTrace();
	}
    }
    
    
}

