Add warning when user destroys default module.
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / ConfigRegistryImpl.java
index 75db0e8d579d4e2cf14c57182ea9a5758ba14714..1b695a9bda2fe42a2fcdd042636e9bff4b0a511d 100644 (file)
@@ -7,32 +7,11 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.annotation.concurrent.ThreadSafe;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
-import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicReadableWrapper;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
@@ -50,6 +29,25 @@ import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.annotation.concurrent.ThreadSafe;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
 /**
  * Singleton that is responsible for creating and committing Config
  * Transactions. It is registered in Platform MBean Server.
@@ -60,6 +58,10 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
     private final ModuleFactoriesResolver resolver;
     private final MBeanServer configMBeanServer;
+
+    @GuardedBy("this")
+    private final BundleContext bundleContext;
+
     @GuardedBy("this")
     private long version = 0;
     @GuardedBy("this")
@@ -112,8 +114,8 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             BundleContext bundleContext, MBeanServer configMBeanServer,
             BaseJMXRegistrator baseJMXRegistrator) {
         this.resolver = resolver;
-        this.beanToOsgiServiceManager = new BeanToOsgiServiceManager(
-                bundleContext);
+        this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
+        this.bundleContext = bundleContext;
         this.configMBeanServer = configMBeanServer;
         this.baseJMXRegistrator = baseJMXRegistrator;
         this.registryMBeanServer = MBeanServerFactory
@@ -127,18 +129,26 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
      */
     @Override
     public synchronized ObjectName beginConfig() {
-        return beginConfigInternal().getControllerObjectName();
+        return beginConfig(false);
     }
 
-    private synchronized ConfigTransactionControllerInternal beginConfigInternal() {
+    /**
+     * @param blankTransaction true if this transaction is created automatically by
+     *                         org.opendaylight.controller.config.manager.impl.osgi.BlankTransactionServiceTracker
+     */
+    public synchronized ObjectName beginConfig(boolean blankTransaction) {
+        return beginConfigInternal(blankTransaction).getControllerObjectName();
+    }
+
+    private synchronized ConfigTransactionControllerInternal beginConfigInternal(boolean blankTransaction) {
         versionCounter++;
         String transactionName = "ConfigTransaction-" + version + "-" + versionCounter;
         TransactionJMXRegistrator transactionRegistrator = baseJMXRegistrator
                 .createTransactionJMXRegistrator(transactionName);
-        List<ModuleFactory> allCurrentFactories = Collections.unmodifiableList(resolver.getAllFactories());
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(resolver.getAllFactories());
         ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
                 transactionName, transactionRegistrator, version,
-                versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer);
+                versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer, blankTransaction);
         try {
             transactionRegistrator.registerMBean(transactionController, transactionController.getControllerObjectName());
         } catch (InstanceAlreadyExistsException e) {
@@ -221,7 +231,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator;
             if (entry.hasOldModule() == false) {
                 runtimeBeanRegistrator = baseJMXRegistrator
-                        .createRuntimeBeanRegistrator(entry.getName());
+                        .createRuntimeBeanRegistrator(entry.getIdentifier());
             } else {
                 // reuse old JMX registrator
                 runtimeBeanRegistrator = entry.getOldInternalInfo()
@@ -234,7 +244,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
                         .setRuntimeBeanRegistrator(runtimeBeanRegistrator);
             }
             // save it to info so it is accessible afterwards
-            runtimeRegistrators.put(entry.getName(), runtimeBeanRegistrator);
+            runtimeRegistrators.put(entry.getIdentifier(), runtimeBeanRegistrator);
         }
 
         // can register runtime beans
@@ -262,8 +272,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             // determine if current instance was recreated or reused or is new
 
             // rules for closing resources:
-            // osgi registration - will be (re)created every time, so it needs
-            // to be closed here
+            // osgi registration - will be reused if possible.
             // module jmx registration - will be (re)created every time, needs
             // to be closed here
             // runtime jmx registration - should be taken care of by module
@@ -272,26 +281,29 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             ModuleJMXRegistrator newModuleJMXRegistrator = baseJMXRegistrator
                     .createModuleJMXRegistrator();
 
+            OsgiRegistration osgiRegistration = null;
             if (entry.hasOldModule()) {
                 ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
                 DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo
                         .getReadableModule();
-                currentConfig.remove(entry.getName());
+                currentConfig.remove(entry.getIdentifier());
 
                 // test if old instance == new instance
-                if (oldReadableConfigBean.getInstance().equals(
-                        module.getInstance())) {
+                if (oldReadableConfigBean.getInstance().equals(module.getInstance())) {
                     // reused old instance:
                     // wrap in readable dynamic mbean
                     reusedInstances.add(primaryReadOnlyON);
+                    osgiRegistration = oldInternalInfo.getOsgiRegistration();
                 } else {
                     // recreated instance:
                     // it is responsibility of module to call the old instance -
                     // we just need to unregister configbean
                     recreatedInstances.add(primaryReadOnlyON);
+
+                    // close old osgi registration
+                    oldInternalInfo.getOsgiRegistration().close();
                 }
-                // close old osgi registration in any case
-                oldInternalInfo.getOsgiRegistration().close();
+
                 // close old module jmx registrator
                 oldInternalInfo.getModuleJMXRegistrator().close();
             } else {
@@ -313,17 +325,25 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             }
 
             // register to OSGi
-            OsgiRegistration osgiRegistration = beanToOsgiServiceManager
-                    .registerToOsgi(module.getClass(),
-                            newReadableConfigBean.getInstance(),
-                            entry.getName());
+            if (osgiRegistration == null) {
+                ModuleFactory moduleFactory = entry.getModuleFactory();
+                if(moduleFactory != null) {
+                    BundleContext bc = configTransactionController.
+                            getModuleFactoryBundleContext(moduleFactory.getImplementationName());
+                    osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(),
+                            newReadableConfigBean.getInstance(), entry.getIdentifier(), bc);
+                } else {
+                    throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found.");
+                }
+
+            }
 
             RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators
-                    .get(entry.getName());
+                    .get(entry.getIdentifier());
             ModuleInternalInfo newInfo = new ModuleInternalInfo(
-                    entry.getName(), newReadableConfigBean, osgiRegistration,
+                    entry.getIdentifier(), newReadableConfigBean, osgiRegistration,
                     runtimeBeanRegistrator, newModuleJMXRegistrator,
-                    orderingIdx);
+                    orderingIdx, entry.isDefaultBean());
 
             newConfigEntries.put(module, newInfo);
             orderingIdx++;
@@ -354,7 +374,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
     /**
      * Abort open transactions and unregister read only modules. Since this
      * class is not responsible for registering itself under
-     * {@link ConfigRegistryMXBean#OBJECT_NAME}, it will not unregister itself
+     * {@link org.opendaylight.controller.config.api.ConfigRegistry#OBJECT_NAME}, it will not unregister itself
      * here.
      */
     @Override