/*
 * 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        "@(#)CIBMBeansFactory.java 1.11     04/08/06 SMI"
 *
 */

package com.sun.mfwk.cib.sdk.util;

// J2SE
import java.util.logging.Logger;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.Hashtable;

// 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 com.sun.jdmk.comm.*;
import javax.management.MBeanServerConnection;

// Cacao
import com.sun.cacao.DeploymentDescriptor;
import com.sun.cacao.Module;
import com.sun.cacao.ModuleMBean;
import com.sun.cacao.container.Container;

// CP
import com.sun.mfwk.util.log.MfLogService;
import com.sun.mfwk.cib.*;
import com.sun.mfwk.cib.providers.CIBProviderHandler;
import com.sun.mfwk.cib.sdk.*;
import com.sun.mfwk.cib.sdk.providers.CIBProviderHandlerImpl;
import com.sun.mfwk.discovery.MfDiscoveryInfo;

/**
 * The CIB Mbeans Factory is a utility class offering CIB Objects creation methods used by JESMF module developers
 * who need to create CIB Objects.
 *
 */
public class CIBMBeansFactory {

  // Keys for CIB objects
  private static final String CIB_KEY_TYPE = "type";
  private static final String CIB_KEY_NAME = "name";     
  private static final String CIB_PROP_TYPE = "Type";

  private Module module = null;

// temporary
  private CIBProviderHandler provider = null;
  private CIBProduct prod = null;

  private Hashtable cibApplis = new Hashtable();
  private Hashtable cibServices = new Hashtable();
  private Hashtable cibAppliResources = new Hashtable();
  private Hashtable cibAppliExternalResources = new Hashtable();
  private Hashtable cibServiceResources = new Hashtable();
  private Hashtable cibServiceExternalResources = new Hashtable();

  /* Tracing utility. */
  private static Logger logger = MfLogService.getLogger("cibMbeansFactory");

  /**
   * Constructor
   * @param m Module : the Module
   *
   */
  public CIBMBeansFactory(Module m) {
    module = m;
  }

  /**
   * Create the CIBProviderHandler
   * This implementation uses the default CIBProviderHandler but if the module has its own providerHandler
   * then you should override this method.
   * @param config MfDiscoveryInfo the discovery message
   */
  public void createCIBProviderHandler(MfDiscoveryInfo config) throws com.sun.
      mfwk.cib.CIBIOException {
    provider = new CIBProviderHandlerImpl(config);
  }

  /**
   * Create the CIBProviderHandler
   * This implementation uses the default CIBProviderHandler but if the module has its own providerHandler
   * then you should override this method.
   * @param conn MBeanServerConnection : the MBeanServerConnection
   */
  public void createCIBProviderHandler(MBeanServerConnection conn) {
    provider = new CIBProviderHandlerImpl(conn);
  }

  /**
   * Creates a CIB product.
   * @param productName String : the CIB product name String
   * @param theProductVersion String : the CIB product version String
   * @param thePatchId String : the CIB product patchId String
   * @param theInstallTime long : the CIB product install time
   * @param theVendorName String : the CIB product vendor name String
   * @return  the newly created CIBProduct.
   */
  public CIBProduct createCIBProduct(String productName,
                                     String theProductVersion,
                                     String thePatchId, long theInstallTime,
                                     String theVendorName) throws
      MBeanRegistrationException {
    try {
      ObjectName productON = new ObjectName(module.getName() +
                                            ":" + CIB_KEY_TYPE + "=CIBProduct,name=" +
                                            productName);
      CIBProduct product = new CIBProduct(productName, theProductVersion,
                                          thePatchId, theInstallTime,
                                          theVendorName);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBProductMBean) product, productON);
      this.prod = product;
      return product;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e, "Couldn't create product MBean");
    }
  }

  /**
   * Creates a CIB application.
   * @param appliName : the CIB application name String
   * @param isStatisticProvider : boolean to indicate that this application exposes Statistics.
   * @param isStateProvider : boolean to indicate that this application exposes States.
   * @param isEventProvider : boolean to indicate that this application is sending events.
   * @return  the newly created CIBApplication.
   */
  public CIBApplication newCIBApplication(String appliName,
                                          boolean isStatisticProvider,
                                          boolean isStateProvider,
                                          boolean isEventProvider) throws
      MBeanRegistrationException {
    try {
      if (this.prod == null) {
        throw new MBeanRegistrationException(null,
            "Couldn't create application before product");
      }
      ObjectName productON = new ObjectName(module.getName() +
                                            ":" + CIB_KEY_TYPE + "=CIBProduct,name=" +
                                            this.prod.getName());
      CIBApplication appli = new CIBApplication();
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appliName + ",CIBProduct=" +
                                          this.prod.getName());
      if (cibApplis.containsKey(appliON)) {
        throw new MBeanRegistrationException(null,
            "This application name as already been created.");
      }
      else {
        cibApplis.put(appliON, appli);
      }
      appli.setCIBProviderHandler(provider);
      appli.setCIBProduct(productON);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBApplicationMBean) appli, appliON);
      provider.createProviders( (CIBApplicationMBean) appli);
      appli.setStatisticProvider(isStatisticProvider);
      appli.setStateProvider(isStateProvider);
      // to be done when events will be supported appli.setEventProvider(isEventProvider)
      ( (CIBProductIf) prod).addApplication(appliON);
      return appli;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
                                           "Couldn't create application MBean ");
    }
  }

  /**
   * Creates a CIB service related to a CIB application
   * @param serviceName : the CIB service name String
   * @param appli : the CIB application
   * @param isStatisticProvider : boolean to indicate that this service exposes Statistics.
   * @param isStateProvider : boolean to indicate that this service exposes States.
   * @param isEventProvider : boolean to indicate that this service is sending events.
   * @return  the newly created CIBService.
   */
  public CIBService newCIBApplicationService(String serviceName,
                                             CIBApplication appli,
                                             boolean isStatisticProvider,
                                             boolean isStateProvider,
                                             boolean isEventProvider) throws
      MBeanRegistrationException {
    try {
      if (this.prod == null) {
        throw new MBeanRegistrationException(null,
            "Couldn't create application service before product");
      }
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appli.getName() +
                                          ",CIBProduct=" + this.prod.getName());
      if (! (com.sun.cacao.container.Container.getMbs()).isRegistered(appliON)) {
        throw new MBeanRegistrationException(null,
            "Couldn't create a service on an application that is not registered");
      }
      CIBService service = new CIBService();
      ObjectName serviceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService,name=" + serviceName +
                                            ",CIBProduct=" + this.prod.getName() +
                                            ",CIBApplication=" + appli.getName());
      if (cibServices.containsKey(serviceON)) {
        throw new MBeanRegistrationException(null,
            "This service name as already been created.");
      }
      else {
        cibServices.put(serviceON, service);
      }
      service.setCIBProviderHandler(provider);
      service.setCIBApplication(appliON);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBServiceMBean) service, serviceON);
      provider.createProviders( (CIBServiceMBean) service);
      if (provider instanceof CIBProviderHandlerImpl) {
        CIBServiceMBean[] serviceMbean = new CIBServiceMBean[1];
        serviceMbean[0] = service;
        ((CIBProviderHandlerImpl)provider).addApplicationProviders( (CIBApplicationMBean) appli,
                                         serviceMbean);
      }
      service.setStatisticProvider(isStatisticProvider);
      service.setStateProvider(isStateProvider);
      // to be done when events will be supported service.setEventProvider(isEventProvider)
      ( (CIBApplicationIf) appli).addCIBService(serviceON);
      return service;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e, "Couldn't create service MBean");
    }
  }

  /**
   * Creates a CIB external resource related to a CIB application
   * @param extresourceName : the CIB external resource name String
   * @param appli : the CIB application
   * @param isStatisticProvider : boolean to indicate that this external resource exposes Statistics.
   * @param isStateProvider : boolean to indicate that this external resource exposes States.
   * @param isEventProvider : boolean to indicate that this external resource is sending events.
   * @return  the newly created CIBExternalResource.
   */
  public CIBExternalResource newCIBApplicationExternalResource(String
      extresourceName, CIBApplication appli, boolean isStatisticProvider,
      boolean isStateProvider, boolean isEventProvider) throws
      MBeanRegistrationException {
    try {
      if (this.prod == null) {
        throw new MBeanRegistrationException(null,
            "Couldn't create application external service before product");
      }
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appli.getName() +
                                          ",CIBProduct=" + this.prod.getName());
      if (! (com.sun.cacao.container.Container.getMbs()).isRegistered(appliON)) {
        throw new MBeanRegistrationException(null,
            "Couldn't create an external service on an application that is not registered");
      }
      // Check that you don't have any extRessource on a service of this application
      // because you can't have external Resource on service AND external Resource on application
      ObjectName[] listOfServices = (ObjectName[]) (com.sun.cacao.container.
          Container.getMbs()).getAttribute(appliON, "Services");
      for (int i = 0; i < listOfServices.length; i++) {
        if ( ( (ObjectName[]) (com.sun.cacao.container.Container.getMbs()).
              getAttribute(listOfServices[i], "ExternalResources")).length != 0) {
          throw new MBeanRegistrationException(null, "Couldn't register external resource on an application if it exists an external resource on a service of this application");
        }
      }
      CIBExternalResource extResource = new CIBExternalResource();
      ObjectName extresourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBExternalResource,name=" +
                                                extresourceName +
                                                ",CIBProduct=" +
                                                this.prod.getName() +
                                                ",CIBApplication=" +
                                                appli.getName());
      if (cibAppliExternalResources.containsKey(extresourceON)) {
        throw new MBeanRegistrationException(null,
            "This external resource name as already been created.");
      }
      else {
        cibAppliExternalResources.put(extresourceON, extResource);
      }
      extResource.setCIBProviderHandler(provider);
      extResource.setCIBApplication(appliON);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBExternalResourceMBean) extResource, extresourceON);
      provider.createProviders( (CIBExternalResourceMBean) extResource);
      extResource.setStatisticProvider(isStatisticProvider);
      extResource.setStateProvider(isStateProvider);
      // to be done when events will be supported extResource.setEventProvider(isEventProvider)
      ( (CIBApplicationIf) appli).addCIBExternalResource(extresourceON);
      return extResource;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
          "Couldn't create external service MBean ");
    }
  }

  /**
   * Creates a CIB resource related to a CIB application
   * @param resourceName : the CIB resource name String
   * @param appli : the CIB application
   * @param isStatisticProvider : boolean to indicate that this resource exposes Statistics.
   * @param isStateProvider : boolean to indicate that this resource exposes States.
   * @param isEventProvider : boolean to indicate that this resource is sending events.
   * @return  the newly created CIBResource.
   */
  public CIBResource newCIBApplicationResource(String resourceName,
                                               CIBApplication appli,
                                               boolean isStatisticProvider,
                                               boolean isStateProvider,
                                               boolean isEventProvider) throws
      MBeanRegistrationException {
    try {
      if (this.prod == null) {
        throw new MBeanRegistrationException(null,
            "Couldn't create application resource before product");
      }
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appli.getName() +
                                          ",CIBProduct=" + this.prod.getName());
      if (! (com.sun.cacao.container.Container.getMbs()).isRegistered(appliON)) {
        throw new MBeanRegistrationException(null,
            "Couldn't create a resource on an application that is not registered");
      }
      CIBResource resource = new CIBResource();
      ObjectName resourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBResource,name=" + resourceName +
                                             ",CIBProduct=" + this.prod.getName() +
                                             ",CIBApplication=" + appli.getName());
      if (cibAppliResources.containsKey(resourceON)) {
        throw new MBeanRegistrationException(null,
            "This resource name as already been created.");
      }
      else {
        cibAppliResources.put(resourceON, resource);
      }
      resource.setCIBProviderHandler(provider);
      resource.setCIBApplication(appliON);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBResourceMBean) resource, resourceON);
      provider.createProviders( (CIBResourceMBean) resource);
      resource.setStatisticProvider(isStatisticProvider);
      resource.setStateProvider(isStateProvider);
      // to be done when events will be supported resource.setEventProvider(isEventProvider)
      ( (CIBApplicationIf) appli).addCIBResource(resourceON);
      return resource;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
                                           "Couldn't create resource MBean  ");
    }
  }

  /**
   * Creates a CIB resource related to a CIB service.
   * @param resourceName : the CIB resource name String
   * @param service : the CIB service
   * @param appli : the CIB application
   * @param isStatisticProvider : boolean to indicate that this resource exposes Statistics.
   * @param isStateProvider : boolean to indicate that this resource exposes States.
   * @param isEventProvider : boolean to indicate that this resource is sending events.
   * @return  the newly created CIBResource.
   */
  public CIBResource newCIBServiceResource(String resourceName,
                                           CIBApplication appli,
                                           CIBService service,
                                           boolean isStatisticProvider,
                                           boolean isStateProvider,
                                           boolean isEventProvider) throws
      MBeanRegistrationException {
    try {
      if (this.prod == null) {
        throw new MBeanRegistrationException(null,
            "Couldn't create resource before product");
      }
      Set listOfServicesON = (com.sun.cacao.container.Container.getMbs()).
          queryNames(new ObjectName(module.getName() + ":*"),
                     Query.and(Query.
                               eq(Query.attr(CIB_PROP_TYPE), Query.value("CIBProduct.CIBApplication.CIBService")),
                               Query.eq(Query.attr("Name"),
                                        Query.value(service.getName()))));
      if (listOfServicesON.size() == 0) {
        throw new MBeanRegistrationException(null,
            "Couldn't register service resource on a service that is not registered");
      }
      CIBResource resource = new CIBResource();
      ObjectName resourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService.CIBResource,name=" +
                                             resourceName + ",CIBProduct=" +
                                             this.prod.getName() +
                                             ",CIBApplication=" + appli.getName() +
                                             ",CIBService=" + service.getName());
      if (cibServiceResources.containsKey(resourceON)) {
        throw new MBeanRegistrationException(null,
            "This resource name as already been created.");
      }
      else {
        cibServiceResources.put(resourceON, resource);
      }
      resource.setCIBProviderHandler(provider);
      ObjectName serviceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService,name=" + service.getName() +
                                            ",CIBProduct=" + this.prod.getName() +
                                            ",CIBApplication=" + appli.getName());
      resource.setCIBService(serviceON);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBResourceMBean) resource, resourceON);
      provider.createProviders( (CIBResourceMBean) resource);
      resource.setStatisticProvider(isStatisticProvider);
      resource.setStateProvider(isStateProvider);
      // to be done when events will be supported resource.setEventProvider(isEventProvider)
      ( (CIBServiceIf) service).addCIBResource(resourceON);
      return resource;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e, "Couldn't create resource MBean ");
    }
  }

  /**
   * Creates a CIB externalResource related to a CIB service.
   * @param extResourceName : the CIB external resource name String
   * @param service : the CIB service
   * @param appli : the CIB application
   * @param isStatisticProvider : boolean to indicate that this externalResource exposes Statistics.
   * @param isStateProvider : boolean to indicate that this externalResource exposes States.
   * @param isEventProvider : boolean to indicate that this externalResource is sending events.
   * @return  the newly created CIBExternalResource.
   */
  public CIBExternalResource newCIBServiceExternalResource(String
      extResourceName, CIBApplication appli, CIBService service,
      boolean isStatisticProvider, boolean isStateProvider,
      boolean isEventProvider) throws MBeanRegistrationException {
    try {
      if (this.prod == null) {
        throw new MBeanRegistrationException(null,
            "Couldn't create extResource before product");
      }
      Set listOfServicesON = (com.sun.cacao.container.Container.getMbs()).
          queryNames(new ObjectName(module.getName() + ":*"),
                     Query.and(Query.
                               eq(Query.attr(CIB_PROP_TYPE), Query.value("CIBProduct.CIBApplication.CIBService")),
                               Query.eq(Query.attr("Name"),
                                        Query.value(service.getName()))));
      if (listOfServicesON.size() == 0) {
        throw new MBeanRegistrationException(null,
            "Couldn't register service extResource on a service that is not registered");
      }
      // Check that you don't have any extRessource on application
      // because you can't have external Resource on service AND external Resource on application
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appli.getName() +
                                          ",CIBProduct=" + this.prod.getName());
      if ( ( (ObjectName[]) (com.sun.cacao.container.Container.getMbs()).
            getAttribute(appliON, "ExternalResources")).length != 0) {
        throw new MBeanRegistrationException(null, "Couldn't register external resource on a service if it exists an external resource on an application");
      }
      CIBExternalResource extResource = new CIBExternalResource();
      ObjectName extResourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService.CIBExternalResource,name=" +
                                                extResourceName +
                                                ",CIBProduct=" +
                                                this.prod.getName() +
                                                ",CIBApplication=" +
                                                appli.getName() +
                                                ",CIBService=" +
                                                service.getName());
      if (cibServiceExternalResources.containsKey(extResourceON)) {
        throw new MBeanRegistrationException(null,
            "This external resource name as already been created.");
      }
      else {
        cibServiceExternalResources.put(extResourceON, extResource);
      }
      extResource.setCIBProviderHandler(provider);
      ObjectName serviceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService,name=" + service.getName() +
                                            ",CIBProduct=" + this.prod.getName() +
                                            ",CIBApplication=" + appli.getName());
      extResource.setCIBService(serviceON);
      (com.sun.cacao.container.Container.getMbs()).registerMBean( (
          CIBExternalResourceMBean) extResource, extResourceON);
      provider.createProviders( (CIBExternalResourceMBean)
                                               extResource);
      extResource.setStatisticProvider(isStatisticProvider);
      extResource.setStateProvider(isStateProvider);
      // to be done when events will be supported extResource.setEventProvider(isEventProvider)
      ( (CIBServiceIf) service).addCIBExternalResource(extResourceON);
      return extResource;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
          "Couldn't create external resource MBean ");
    }
  }

  /**
   * Removes a CIB product and all the CIB Mbeans relative to this product.
   * @param productName
   */
  public void removeCIBProduct(String productName) throws
      MBeanRegistrationException {
    try {
      ObjectName productON = new ObjectName(module.getName() +
                                            ":" + CIB_KEY_TYPE + "=CIBProduct,name=" +
                                            productName);
      ObjectName[] listOfApplications = (ObjectName[]) com.sun.cacao.container.
          Container.getMbs().getAttribute(productON, "Applications");
      for (int i = 0; i < listOfApplications.length; i++) {
        removeCIBApplication(listOfApplications[i].getKeyProperty("name"));
      }
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(productON);
      this.prod = null;
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
                                           "Couldn't unregister product MBean");
    }
  }

  /**
   * Removes a CIB application and all the CIB Mbeans relative to this application.
   * @param appliName : the CIB application name String
   */
  public void removeCIBApplication(String appliName) throws
      MBeanRegistrationException {
    try {
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appliName + ",CIBProduct=" +
                                          this.prod.getName());
      ObjectName[] listOfServices = (ObjectName[]) com.sun.cacao.container.
          Container.getMbs().getAttribute(appliON, "Services");
      for (int i = 0; i < listOfServices.length; i++) {
        removeCIBApplicationService(listOfServices[i].getKeyProperty("name"),
                                    appliName);
      }
      ObjectName[] listOfResources = (ObjectName[]) com.sun.cacao.container.
          Container.getMbs().getAttribute(appliON, "Resources");
      for (int j = 0; j < listOfResources.length; j++) {
        removeCIBApplicationResource(listOfResources[j].getKeyProperty("name"),
                                     appliName);
      }
      ObjectName[] listOfExternalResources = (ObjectName[]) com.sun.cacao.
          container.Container.getMbs().getAttribute(appliON,
          "ExternalResources");
      for (int k = 0; k < listOfExternalResources.length; k++) {
        removeCIBApplicationExternalResource(listOfExternalResources[k].
                                             getKeyProperty("name"), appliName);
      }
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(appliON);
      ( (CIBProductIf) prod).removeApplication(appliON);
      cibApplis.remove(appliON);
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
          "Couldn't unregister application MBean ");
    }
  }

  /**
   * Removes a CIB service related to a CIB application and all the CIB Mbeans relative to this service.
   * @param serviceName String : the CIB service name String
   * @param appliName String : the CIB application name String
   */
  public void removeCIBApplicationService(String serviceName, String appliName) throws
      MBeanRegistrationException {
    try {
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appliName + ",CIBProduct=" +
                                          this.prod.getName());
      ObjectName serviceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService,name=" + serviceName +
                                            ",CIBProduct=" + this.prod.getName() +
                                            ",CIBApplication=" + appliName);
      ObjectName[] listOfResources = (ObjectName[]) com.sun.cacao.container.
          Container.getMbs().getAttribute(serviceON, "Resources");
      for (int j = 0; j < listOfResources.length; j++) {
        removeCIBServiceResource(listOfResources[j].getKeyProperty("name"),
                                 serviceName, appliName);
      }
      ObjectName[] listOfExternalResources = (ObjectName[]) com.sun.cacao.
          container.Container.getMbs().getAttribute(serviceON,
          "ExternalResources");
      for (int k = 0; k < listOfExternalResources.length; k++) {
        removeCIBServiceExternalResource(listOfExternalResources[k].
                                         getKeyProperty("name"), serviceName,
                                         appliName);
      }
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(serviceON);
      ( (CIBApplicationIf) cibApplis.get(appliON)).removeCIBService(serviceON);
      cibServices.remove(serviceON);
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
                                           "Couldn't unregister service MBean ");
    }
  }

  /**
   * Removes a CIB resource related to a CIB application
   * @param resourceName String : the CIB resource name String
   * @param appliName String : the CIB application name String
   */
  public void removeCIBApplicationResource(String resourceName,
                                           String appliName) throws
      MBeanRegistrationException {
    try {
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appliName + ",CIBProduct=" +
                                          this.prod.getName());
      ObjectName resourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBResource,name=" + resourceName +
                                             ",CIBProduct=" + this.prod.getName() +
                                             ",CIBApplication=" + appliName);
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(resourceON);
      ( (CIBApplicationIf) cibApplis.get(appliON)).removeCIBResource(
          resourceON);
      cibAppliResources.remove(resourceON);
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
                                           "Couldn't unregister resource MBean");
    }
  }

  /**
   * Removes a CIB external resource related to a CIB application
   * @param extResourceName String : the CIB external resource name String
   * @param appliName String : the CIB application name String
   */
  public void removeCIBApplicationExternalResource(String extResourceName,
      String appliName) throws MBeanRegistrationException {
    try {
      ObjectName appliON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication,name=" + appliName + ",CIBProduct=" +
                                          this.prod.getName());
      ObjectName extresourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBExternalResource,name=" +
                                                extResourceName +
                                                ",CIBProduct=" +
                                                this.prod.getName() +
                                                ",CIBApplication=" + appliName);
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(
          extresourceON);
      ( (CIBApplicationIf) cibApplis.get(appliON)).removeCIBExternalResource(
          extresourceON);
      cibAppliExternalResources.remove(extresourceON);
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
          "Couldn't unregister external resource MBean");
    }
  }

  /**
   * Removes a CIB resource related to a CIB service
   * @param resourceName : the CIB resource name String
   * @param serviceName : the CIB service name String
   */
  public void removeCIBServiceResource(String resourceName, String serviceName,
                                       String appliName) throws
      MBeanRegistrationException {
    try {
      ObjectName serviceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService,name=" + serviceName +
                                            ",CIBProduct=" + this.prod.getName() +
                                            ",CIBApplication=" + appliName);
      ObjectName resourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService.CIBResource,name=" +
                                             resourceName + ",CIBProduct=" +
                                             this.prod.getName() +
                                             ",CIBApplication=" + appliName +
                                             ",CIBService=" + serviceName);
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(resourceON);
      ( (CIBServiceIf) cibServices.get(serviceON)).removeCIBResource(
          resourceON);
      cibServiceResources.remove(resourceON);
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
                                           "Couldn't unregister resource MBean");
    }
  }

  /**
   * Removes a CIB external resource related to a CIB service
   * @param extResourceName : the CIB resource name String
   * @param serviceName : the CIB service name String
   */
  public void removeCIBServiceExternalResource(String extResourceName,
                                               String serviceName,
                                               String appliName) throws
      MBeanRegistrationException {
    try {
      ObjectName serviceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService,name=" + serviceName +
                                            ",CIBProduct=" + this.prod.getName() +
                                            ",CIBApplication=" + appliName);
      ObjectName extresourceON = new ObjectName(module.getName() +
          ":" + CIB_KEY_TYPE + "=CIBProduct.CIBApplication.CIBService.CIBExternalResource,name=" +
                                                extResourceName +
                                                ",CIBProduct=" +
                                                this.prod.getName() +
                                                ",CIBApplication=" + appliName +
                                                ",CIBService=" + serviceName);
      (com.sun.cacao.container.Container.getMbs()).unregisterMBean(
          extresourceON);
      ( (CIBServiceIf) cibServices.get(serviceON)).removeCIBExternalResource(
          extresourceON);
      cibServiceExternalResources.remove(extresourceON);
    }
    catch (Exception e) {
      throw new MBeanRegistrationException(e,
          "Couldn't unregister external resource MBean");
    }
  }

}
