Add service reference binding to config registry. 69/3569/8
authorTomas Olvecky <tolvecky@cisco.com>
Mon, 9 Dec 2013 12:20:56 +0000 (13:20 +0100)
committerTomas Olvecky <tolvecky@cisco.com>
Wed, 11 Dec 2013 10:46:32 +0000 (11:46 +0100)
Add a database for persisting service references between commits. In netconf modules
are wired together via link in /services/service xml subtree. Each service has an
xpath pointer back to a /modules/module that implements the service. Consumer of a
service then maintains a link to the service via its namespace and reference name.
This commit fixes problem of reference names not surviving commits.

Change-Id: I784f99617bb0072fc4dc3762a28e30f9b9bcf111
Signed-off-by: Tomas Olvecky <tolvecky@cisco.com>
37 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java [new file with mode: 0644]
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java [new file with mode: 0644]
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/annotations/ServiceInterfaceAnnotation.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/spi/ModuleFactory.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerInternal.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionJMXRegistrator.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ClassBasedModuleFactory.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImplTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dynamicmbean/AnnotationsTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPConfigMXBean.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModuleFactory.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModuleFactory.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/ModifiableThreadPoolServiceInterface.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingScheduledThreadPoolServiceInterface.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/TestingFixedThreadPoolModuleFactory.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/LookupTest.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/ftl/model/Annotation.java
opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/factory_abs_template.ftl
opendaylight/config/yang-jmx-generator-plugin/src/test/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/JMXGeneratorTest.java

index 5f23c90..56b96e9 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConsta
  * Provides functionality for working with configuration registry - mainly
  * creating and committing config transactions.
  */
-public interface ConfigRegistry extends LookupRegistry {
+public interface ConfigRegistry extends LookupRegistry, ServiceReferenceReadableRegistry {
 
     /**
      * Only well-known ObjectName in configuration system, under which
index 7e8ee64..c257e55 100644 (file)
@@ -16,7 +16,7 @@ import javax.management.ObjectName;
 /**
  * Represents functionality provided by configuration transaction.
  */
-public interface ConfigTransactionController extends LookupRegistry {
+public interface ConfigTransactionController extends LookupRegistry, ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
 
     /**
      * Create new configuration bean.
@@ -64,6 +64,9 @@ public interface ConfigTransactionController extends LookupRegistry {
      */
     String getTransactionName();
 
+    /**
+     * @return all known module factory names as reported by {@link org.opendaylight.controller.config.spi.ModuleFactory#getImplementationName()}
+     */
     Set<String> getAvailableModuleNames();
 
 }
index 7a3c4bf..8975471 100644 (file)
@@ -7,10 +7,9 @@
  */
 package org.opendaylight.controller.config.api;
 
-import java.util.Set;
-
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
+import java.util.Set;
 
 public interface LookupRegistry {
 
@@ -58,4 +57,12 @@ public interface LookupRegistry {
     ObjectName lookupConfigBean(String moduleName, String instanceName)
             throws InstanceNotFoundException;
 
+    /**
+     * Check that object name corresponds with existing module.
+     *
+     * @throws InstanceNotFoundException
+     *             if search did not find exactly one instance
+     */
+    void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException;
+
 }
diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java
new file mode 100644 (file)
index 0000000..f84fcd4
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.api;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Set;
+
+public interface ServiceReferenceReadableRegistry {
+
+    /**
+     * Lookup object name by fully qualified service interface name and service reference name.
+     * @param serviceInterfaceName service interface name
+     * @param refName service reference name supplied in
+     * {@link org.opendaylight.controller.config.api.ConfigTransactionController#saveServiceReference(String, String, javax.management.ObjectName)}
+     * @throws java.lang.IllegalArgumentException if module not found
+     */
+    ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName);
+
+    /**
+     * Get mapping of services to reference names and module object names.
+     */
+    Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping();
+
+    /**
+     * Get current mapping between reference names and module object names for given service interface name.
+     * @param serviceInterfaceName service interface name
+     * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName
+     */
+    Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName);
+
+    /**
+     * Find all available service interface names of a module.
+     * @param objectName module object name
+     * @throws InstanceNotFoundException if search did not find exactly one instance
+     */
+    Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException;
+
+    /**
+     * @param namespace service interface namespace
+     * @param localName service interface local name
+     * @return fully qualified name needed by all other service reference mapping methods.
+     * @throws java.lang.IllegalArgumentException if namespace or localName is not found
+     */
+    String getServiceInterfaceName(String namespace, String localName);
+
+}
diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java
new file mode 100644 (file)
index 0000000..f3d6d16
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.api;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
+public interface ServiceReferenceWritableRegistry extends ServiceReferenceReadableRegistry {
+    /**
+     * Create or update reference name to objectName. Reference name is unique per service interface name.
+     * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName
+     * @throws InstanceNotFoundException if search did not find exactly one instance
+     */
+    void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException;
+
+    /**
+     * Remove service reference.
+     * @return true iif removed
+     * @throws IllegalArgumentException if service interface name is not advertised by any module
+     */
+    boolean removeServiceReference(String serviceInterfaceName, String refName);
+
+    /**
+     * Remove all service references.
+     */
+    void removeAllServiceReferences();
+
+    /**
+     * Remove all service references attached to given module.
+     * @return true iif at least one reference was removed
+     */
+    boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException;
+}
index a81d992..e66de46 100644 (file)
@@ -23,8 +23,9 @@ import java.lang.annotation.Target;
 public @interface ServiceInterfaceAnnotation {
 
     /**
-     * Specifies human readable name of this service. Each service name should
-     * be globally unique. Should not contain spaces.
+     * Fully qualified name of a service that must be globally unique.
+     * When generating service interfaces from yang, this will be QName of
+     * identity extending service-type.
      */
     String value();
 
@@ -34,4 +35,19 @@ public @interface ServiceInterfaceAnnotation {
      * is called.
      */
     Class<?> osgiRegistrationType();
+
+    /**
+     * Get namespace of {@link #value()}
+     */
+    String namespace();
+
+    /**
+     * Get revision of {@link #value()}
+     */
+    String revision();
+
+    /**
+     * Get local name of {@link #value()}
+     */
+    String localName();
 }
index 8111690..cc1d897 100644 (file)
@@ -7,6 +7,11 @@
  */
 package org.opendaylight.controller.config.api.jmx;
 
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
+
+import javax.annotation.concurrent.ThreadSafe;
+import javax.management.ObjectName;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -15,12 +20,6 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-import javax.annotation.concurrent.ThreadSafe;
-import javax.management.ObjectName;
-
-import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
-
 /**
  * Provides ObjectName creation. Each created ObjectName consists of domain that
  * is defined as {@link #ON_DOMAIN} and at least one key-value pair. The only
@@ -129,18 +128,31 @@ public class ObjectNameUtil {
         return objectName.getKeyProperty(TRANSACTION_NAME_KEY);
     }
 
-    public static ObjectName withoutTransactionName(ObjectName on) {
-        if (getTransactionName(on) == null) {
+    /**
+     * Sanitize on: keep only mandatory attributes of module + metadata.
+     */
+    public static ObjectName withoutTransactionName(ObjectName inputON) {
+        if (getTransactionName(inputON) == null) {
             throw new IllegalArgumentException(
-                    "Expected ObjectName with transaction:" + on);
+                    "Expected ObjectName with transaction:" + inputON);
         }
-        if (ON_DOMAIN.equals(on.getDomain()) == false) {
+        if (ON_DOMAIN.equals(inputON.getDomain()) == false) {
             throw new IllegalArgumentException("Expected different domain: "
-                    + on);
+                    + inputON);
+        }
+        String moduleName = getFactoryName(inputON);
+        String instanceName = getInstanceName(inputON);
+
+
+        Map<String, String> allProperties = getAdditionalProperties(inputON);
+        Map<String, String> outputProperties = new HashMap<>(createModuleON(moduleName, instanceName));
+
+        for(Entry<String, String> entry: allProperties.entrySet()) {
+            if (entry.getKey().startsWith("X-")) {
+                outputProperties.put(entry.getKey(), entry.getValue());
+            }
         }
-        String moduleName = getFactoryName(on);
-        String instanceName = getInstanceName(on);
-        return createReadOnlyModuleON(moduleName, instanceName);
+        return createON(ON_DOMAIN, outputProperties);
     }
 
     private static void assertDoesNotContain(
index 7b8f7c1..c86b381 100644 (file)
@@ -97,6 +97,8 @@ public interface ModuleFactory {
     boolean isModuleImplementingServiceInterface(
             Class<? extends AbstractServiceInterface> serviceInterface);
 
+    Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces();
+
     /**
      * Called when ModuleFactory is registered to config manager.
      * Useful for populating the registry with pre-existing state. Since
index 1b695a9..18326d9 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.controller.config.manager.impl;
 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.ServiceReferenceReadableRegistry;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
@@ -102,6 +104,9 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
     @GuardedBy("this")
     private List<ModuleFactory> lastListOfFactories = Collections.emptyList();
 
+    @GuardedBy("this") // switched in every 2ndPC
+    private ServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
+
     // constructor
     public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
             BundleContext bundleContext, MBeanServer configMBeanServer) {
@@ -142,21 +147,32 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
     private synchronized ConfigTransactionControllerInternal beginConfigInternal(boolean blankTransaction) {
         versionCounter++;
-        String transactionName = "ConfigTransaction-" + version + "-" + versionCounter;
-        TransactionJMXRegistrator transactionRegistrator = baseJMXRegistrator
-                .createTransactionJMXRegistrator(transactionName);
-        Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(resolver.getAllFactories());
+        final String transactionName = "ConfigTransaction-" + version + "-" + versionCounter;
+
+        TransactionJMXRegistratorFactory factory = new TransactionJMXRegistratorFactory() {
+            @Override
+            public TransactionJMXRegistrator create() {
+                return baseJMXRegistrator.createTransactionJMXRegistrator(transactionName);
+            }
+        };
+
+        ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier(
+                transactionName), factory);
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(
+                resolver.getAllFactories());
+        ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+                readableSRRegistry, txLookupRegistry, allCurrentFactories);
+
         ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
-                transactionName, transactionRegistrator, version,
-                versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer, blankTransaction);
+                txLookupRegistry, version,
+                versionCounter, allCurrentFactories, transactionsMBeanServer,
+                configMBeanServer, blankTransaction, writableRegistry);
         try {
-            transactionRegistrator.registerMBean(transactionController, transactionController.getControllerObjectName());
+            txLookupRegistry.registerMBean(transactionController, transactionController.getControllerObjectName());
         } catch (InstanceAlreadyExistsException e) {
             throw new IllegalStateException(e);
         }
-
         transactionController.copyExistingModulesAndProcessFactoryDiff(currentConfig.getEntries(), lastListOfFactories);
-
         transactionsHolder.add(transactionName, transactionController);
         return transactionController;
     }
@@ -352,6 +368,10 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
         // update version
         version = configTransactionController.getVersion();
+
+        // switch readable Service Reference Registry
+        this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(configTransactionController.getWritableRegistry(), this);
+
         return new CommitStatus(newInstances, reusedInstances,
                 recreatedInstances);
     }
@@ -493,6 +513,43 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
         return baseJMXRegistrator.queryNames(namePattern, null);
     }
 
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        ObjectNameUtil.checkDomain(objectName);
+        ObjectNameUtil.checkType(objectName, ObjectNameUtil.TYPE_MODULE);
+        String transactionName = ObjectNameUtil.getTransactionName(objectName);
+        if (transactionName != null) {
+            throw new IllegalArgumentException("Transaction attribute not supported in registry, wrong ObjectName: " + objectName);
+        }
+        // make sure exactly one match is found:
+        LookupBeansUtil.lookupConfigBean(this, ObjectNameUtil.getFactoryName(objectName), ObjectNameUtil.getInstanceName(objectName));
+    }
+
+    // service reference functionality:
+    @Override
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    }
+
+    @Override
+    public synchronized Map<String, Map<String, ObjectName>> getServiceMapping() {
+        return readableSRRegistry.getServiceMapping();
+    }
+
+    @Override
+    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    }
+
+    @Override
+    public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        return readableSRRegistry.lookupServiceInterfaceNames(objectName);
+    }
+
+    @Override
+    public synchronized String getServiceInterfaceName(String namespace, String localName) {
+        return readableSRRegistry.getServiceInterfaceName(namespace, localName);
+    }
 }
 
 /**
index 3e53a7a..36485b1 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl;
 
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
@@ -16,10 +17,8 @@ import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWrita
 import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean;
 import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
-import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
-import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.yangtools.concepts.Identifiable;
@@ -47,7 +46,7 @@ import static java.lang.String.format;
 
 /**
  * This is a JMX bean representing current transaction. It contains
- * {@link #transactionIdentifier}, unique version and parent version for
+ * transaction identifier, unique version and parent version for
  * optimistic locking.
  */
 class ConfigTransactionControllerImpl implements
@@ -56,10 +55,9 @@ class ConfigTransactionControllerImpl implements
         Identifiable<TransactionIdentifier>{
     private static final Logger logger = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);
 
-    private final TransactionIdentifier transactionIdentifier;
+    private final ConfigTransactionLookupRegistry txLookupRegistry;
     private final ObjectName controllerON;
-    private final TransactionJMXRegistrator transactionRegistrator;
-    private final TransactionModuleJMXRegistrator txModuleJMXRegistrator;
+
     private final long parentVersion, currentVersion;
     private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder;
     private final DependencyResolverManager dependencyResolverManager;
@@ -80,19 +78,18 @@ class ConfigTransactionControllerImpl implements
 
     private final boolean blankTransaction;
 
-    public ConfigTransactionControllerImpl(String transactionName,
-                                           TransactionJMXRegistrator transactionRegistrator,
+    @GuardedBy("this")
+    private final ServiceReferenceWritableRegistry writableSRRegistry;
+
+    public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
                                            long parentVersion, long currentVersion,
                                            Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
                                            MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
-                                           boolean blankTransaction) {
-
-        this.transactionIdentifier = new TransactionIdentifier(transactionName);
-        this.controllerON = ObjectNameUtil
-                .createTransactionControllerON(transactionName);
-        this.transactionRegistrator = transactionRegistrator;
-        txModuleJMXRegistrator = transactionRegistrator
-                .createTransactionModuleJMXRegistrator();
+                                           boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) {
+
+        this.txLookupRegistry = txLookupRegistry;
+        String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
+        this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
         this.parentVersion = parentVersion;
         this.currentVersion = currentVersion;
         this.currentlyRegisteredFactories = currentlyRegisteredFactories;
@@ -102,6 +99,7 @@ class ConfigTransactionControllerImpl implements
         this.transactionsMBeanServer = transactionsMBeanServer;
         this.configMBeanServer = configMBeanServer;
         this.blankTransaction = blankTransaction;
+        this.writableSRRegistry = writableSRRegistry;
     }
 
     @Override
@@ -225,14 +223,14 @@ class ConfigTransactionControllerImpl implements
                     + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
         }
         DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
-                module, moduleIdentifier, transactionIdentifier,
+                module, moduleIdentifier, getTransactionIdentifier(),
                 readOnlyAtomicBoolean, transactionsMBeanServer,
                 configMBeanServer);
 
         ObjectName writableON = ObjectNameUtil.createTransactionModuleON(
-                transactionIdentifier.getName(), moduleIdentifier);
+                getTransactionIdentifier().getName(), moduleIdentifier);
         // put wrapper to jmx
-        TransactionModuleJMXRegistration transactionModuleJMXRegistration = txModuleJMXRegistrator
+        TransactionModuleJMXRegistration transactionModuleJMXRegistration = getTxModuleJMXRegistrator()
                 .registerMBean(writableDynamicWrapper, writableON);
         ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo(
                 moduleIdentifier, module, moduleFactory,
@@ -243,18 +241,21 @@ class ConfigTransactionControllerImpl implements
     }
 
     @Override
-    public synchronized void destroyModule(ObjectName objectName)
-            throws InstanceNotFoundException {
+    public synchronized void destroyModule(ObjectName objectName) throws InstanceNotFoundException {
+        checkTransactionName(objectName);
+        ObjectNameUtil.checkDomain(objectName);
+        ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName,
+                ObjectNameUtil.TYPE_MODULE);
+        destroyModule(moduleIdentifier);
+    }
+
+    private void checkTransactionName(ObjectName objectName) {
         String foundTransactionName = ObjectNameUtil
                 .getTransactionName(objectName);
-        if (transactionIdentifier.getName().equals(foundTransactionName) == false) {
+        if (getTransactionIdentifier().getName().equals(foundTransactionName) == false) {
             throw new IllegalArgumentException("Wrong transaction name "
                     + objectName);
         }
-        ObjectNameUtil.checkDomain(objectName);
-        ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName,
-                ObjectNameUtil.TYPE_MODULE);
-        destroyModule(moduleIdentifier);
     }
 
     private synchronized void destroyModule(ModuleIdentifier moduleIdentifier) {
@@ -268,6 +269,15 @@ class ConfigTransactionControllerImpl implements
                 logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem");
             }
         }
+        // first remove refNames, it checks for objectname existence
+        try {
+            writableSRRegistry.removeServiceReferences(
+                    ObjectNameUtil.createTransactionModuleON(getTransactionName(),moduleIdentifier));
+        } catch (InstanceNotFoundException e) {
+            logger.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry);
+            throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e);
+        }
+
         ModuleInternalTransactionalInfo removedTInfo = dependencyResolverManager.destroyModule(moduleIdentifier);
         // remove from jmx
         removedTInfo.getTransactionModuleJMXRegistration().close();
@@ -297,7 +307,7 @@ class ConfigTransactionControllerImpl implements
 
     private void validate_noLocks() throws ValidationException {
         transactionStatus.checkNotAborted();
-        logger.info("Validating transaction {}", transactionIdentifier);
+        logger.info("Validating transaction {}", getTransactionIdentifier());
         // call validate()
         List<ValidationException> collectedExceptions = new ArrayList<>();
         for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
@@ -317,7 +327,7 @@ class ConfigTransactionControllerImpl implements
             throw ValidationException
                     .createFromCollectedValidationExceptions(collectedExceptions);
         }
-        logger.info("Validated transaction {}", transactionIdentifier);
+        logger.info("Validated transaction {}", getTransactionIdentifier());
     }
 
     /**
@@ -359,7 +369,7 @@ class ConfigTransactionControllerImpl implements
                             + "to obtain a lock");
         }
 
-        logger.info("Committing transaction {}", transactionIdentifier);
+        logger.info("Committing transaction {}", getTransactionIdentifier());
 
         // call getInstance()
         for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
@@ -368,21 +378,21 @@ class ConfigTransactionControllerImpl implements
             ModuleIdentifier name = entry.getKey();
             try {
                 logger.debug("About to commit {} in transaction {}",
-                        name, transactionIdentifier);
+                        name, getTransactionIdentifier());
                 module.getInstance();
             } catch (Exception e) {
                 logger.error("Commit failed on {} in transaction {}", name,
-                        transactionIdentifier, e);
+                        getTransactionIdentifier(), e);
                 internalAbort();
                 throw new RuntimeException(
                         format("Error - getInstance() failed for %s in transaction %s",
-                                name, transactionIdentifier), e);
+                                name, getTransactionIdentifier()), e);
             }
         }
 
         // count dependency order
 
-        logger.info("Committed configuration {}", transactionIdentifier);
+        logger.info("Committed configuration {}", getTransactionIdentifier());
         transactionStatus.setCommitted();
         // unregister this and all modules from jmx
         close();
@@ -403,7 +413,8 @@ class ConfigTransactionControllerImpl implements
     }
 
     private void close() {
-        transactionRegistrator.close();
+        //FIXME: should not close object that was retrieved in constructor, a wrapper object should do that perhaps
+        txLookupRegistry.close();
     }
 
     @Override
@@ -413,7 +424,7 @@ class ConfigTransactionControllerImpl implements
 
     @Override
     public String getTransactionName() {
-        return transactionIdentifier.getName();
+        return getTransactionIdentifier().getName();
     }
 
     /**
@@ -421,7 +432,7 @@ class ConfigTransactionControllerImpl implements
      */
     @Override
     public Set<ObjectName> lookupConfigBeans() {
-        return lookupConfigBeans("*", "*");
+        return txLookupRegistry.lookupConfigBeans();
     }
 
     /**
@@ -429,7 +440,7 @@ class ConfigTransactionControllerImpl implements
      */
     @Override
     public Set<ObjectName> lookupConfigBeans(String moduleName) {
-        return lookupConfigBeans(moduleName, "*");
+        return txLookupRegistry.lookupConfigBeans(moduleName);
     }
 
     /**
@@ -438,20 +449,29 @@ class ConfigTransactionControllerImpl implements
     @Override
     public ObjectName lookupConfigBean(String moduleName, String instanceName)
             throws InstanceNotFoundException {
-        return LookupBeansUtil.lookupConfigBean(this, moduleName, instanceName);
+        return txLookupRegistry.lookupConfigBean(moduleName, instanceName);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public Set<ObjectName> lookupConfigBeans(String moduleName,
-            String instanceName) {
-        ObjectName namePattern = ObjectNameUtil.createModulePattern(moduleName,
-                instanceName, transactionIdentifier.getName());
-        return txModuleJMXRegistrator.queryNames(namePattern, null);
+    public Set<ObjectName> lookupConfigBeans(String moduleName, String instanceName) {
+        return txLookupRegistry.lookupConfigBeans(moduleName, instanceName);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        txLookupRegistry.checkConfigBeanExists(objectName);
+    }
+    // --
+
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Set<String> getAvailableModuleNames() {
         return factoriesHolder.getModuleNames();
@@ -473,11 +493,11 @@ class ConfigTransactionControllerImpl implements
     // @VisibleForTesting
 
     TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() {
-        return txModuleJMXRegistrator;
+        return txLookupRegistry.getTxModuleJMXRegistrator();
     }
 
     public TransactionIdentifier getName() {
-        return transactionIdentifier;
+        return getTransactionIdentifier();
     }
 
     @Override
@@ -487,7 +507,7 @@ class ConfigTransactionControllerImpl implements
 
     @Override
     public TransactionIdentifier getIdentifier() {
-        return transactionIdentifier;
+        return getTransactionIdentifier();
     }
 
     @Override
@@ -498,4 +518,62 @@ class ConfigTransactionControllerImpl implements
         }
         return factoryBundleContextEntry.getValue();
     }
+
+    // service reference functionality:
+
+
+    @Override
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    }
+
+    @Override
+    public synchronized Map<String, Map<String, ObjectName>> getServiceMapping() {
+        return writableSRRegistry.getServiceMapping();
+    }
+
+    @Override
+    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    }
+
+    @Override
+    public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        return writableSRRegistry.lookupServiceInterfaceNames(objectName);
+    }
+
+    @Override
+    public synchronized String getServiceInterfaceName(String namespace, String localName) {
+        return writableSRRegistry.getServiceInterfaceName(namespace, localName);
+    }
+
+    @Override
+    public synchronized void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
+        writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, objectName);
+    }
+
+    @Override
+    public synchronized boolean removeServiceReference(String serviceInterfaceName, String refName) {
+        return writableSRRegistry.removeServiceReference(serviceInterfaceName, refName);
+    }
+
+    @Override
+    public synchronized void removeAllServiceReferences() {
+        writableSRRegistry.removeAllServiceReferences();
+    }
+
+    @Override
+    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
+        return writableSRRegistry.removeServiceReferences(objectName);
+    }
+
+    @Override
+    public ServiceReferenceWritableRegistry getWritableRegistry() {
+        return writableSRRegistry;
+    }
+
+    public TransactionIdentifier getTransactionIdentifier() {
+        return txLookupRegistry.getTransactionIdentifier();
+    }
+
 }
index 4dc877c..82bae44 100644 (file)
@@ -13,6 +13,7 @@ import java.util.List;
 import javax.management.ObjectName;
 
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
@@ -71,4 +72,7 @@ interface ConfigTransactionControllerInternal extends
     List<ModuleFactory> getCurrentlyRegisteredFactories();
 
     BundleContext getModuleFactoryBundleContext(String factoryName);
+
+    ServiceReferenceWritableRegistry getWritableRegistry();
+
 }
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java
new file mode 100644 (file)
index 0000000..5d1f0b3
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl;
+
+import org.opendaylight.controller.config.api.LookupRegistry;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
+import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
+import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.io.Closeable;
+import java.util.Set;
+
+/**
+ * Responsible for creating TransactionJMXRegistrator, registering transaction and all its beans,
+ * lookup of beans, closing of TransactionJMXRegistrator.
+ */
+class ConfigTransactionLookupRegistry  implements LookupRegistry, Closeable {
+    private final TransactionJMXRegistrator transactionJMXRegistrator;
+    private final TransactionIdentifier transactionIdentifier;
+    private final TransactionModuleJMXRegistrator txModuleJMXRegistrator;
+
+    ConfigTransactionLookupRegistry(TransactionIdentifier transactionIdentifier,
+                                    TransactionJMXRegistratorFactory factory) {
+        this.transactionIdentifier = transactionIdentifier;
+        this.transactionJMXRegistrator = factory.create();
+        this.txModuleJMXRegistrator = transactionJMXRegistrator.createTransactionModuleJMXRegistrator();
+    }
+
+    private void checkTransactionName(ObjectName objectName) {
+        String foundTransactionName = ObjectNameUtil
+                .getTransactionName(objectName);
+        if (transactionIdentifier.getName().equals(foundTransactionName) == false) {
+            throw new IllegalArgumentException("Wrong transaction name "
+                    + objectName);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupConfigBeans() {
+        return lookupConfigBeans("*", "*");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupConfigBeans(String moduleName) {
+        return lookupConfigBeans(moduleName, "*");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ObjectName lookupConfigBean(String moduleName, String instanceName)
+            throws InstanceNotFoundException {
+        return LookupBeansUtil.lookupConfigBean(this, moduleName, instanceName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Set<ObjectName> lookupConfigBeans(String moduleName,
+                                             String instanceName) {
+        ObjectName namePattern = ObjectNameUtil.createModulePattern(moduleName,
+                instanceName, transactionIdentifier.getName());
+        return txModuleJMXRegistrator.queryNames(namePattern, null);
+    }
+
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        ObjectNameUtil.checkDomain(objectName);
+        ObjectNameUtil.checkType(objectName, ObjectNameUtil.TYPE_MODULE);
+        checkTransactionName(objectName);
+        // make sure exactly one match is found:
+        LookupBeansUtil.lookupConfigBean(this, ObjectNameUtil.getFactoryName(objectName), ObjectNameUtil.getInstanceName(objectName));
+    }
+
+    TransactionIdentifier getTransactionIdentifier() {
+        return transactionIdentifier;
+    }
+
+    TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() {
+        return txModuleJMXRegistrator;
+    }
+
+    public void close() {
+        transactionJMXRegistrator.close();
+    }
+
+    public void registerMBean(ConfigTransactionControllerInternal transactionController, ObjectName controllerObjectName) throws InstanceAlreadyExistsException {
+        transactionJMXRegistrator.registerMBean(transactionController, controllerObjectName);
+    }
+}
+
+interface TransactionJMXRegistratorFactory {
+    TransactionJMXRegistrator create();
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java
new file mode 100644 (file)
index 0000000..2fd1ca6
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl;
+
+import org.opendaylight.controller.config.api.LookupRegistry;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+    private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
+
+    private final Map<String, ModuleFactory> factories;
+    private final Map<String, Set<String>> factoryNamesToQNames;
+    // validator of incoming ObjectNames - throws InstanceNotFoundException if not found either in registry or transaction
+    private final LookupRegistry lookupRegistry;
+    // helper method for getting QName of SI from namespace + local name
+    private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
+    // all Service Interface qNames for sanity checking
+    private final Set<String /* qName */> allQNames;
+
+    // actual reference database
+    private final Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> refNames;
+
+    /**
+     * Static constructor for config registry. Since only transaction can write to this registry, it will
+     * return blank state.
+     */
+    public static ServiceReferenceReadableRegistry createInitialSRLookupRegistry() {
+        // since this is initial state, just throw exception:
+        LookupRegistry lookupRegistry = new LookupRegistry() {
+            @Override
+            public Set<ObjectName> lookupConfigBeans() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Set<ObjectName> lookupConfigBeans(String moduleName) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Set<ObjectName> lookupConfigBeans(String moduleName, String instanceName) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+                throw new InstanceNotFoundException("Cannot find " + objectName);
+            }
+        };
+        return new ServiceReferenceRegistryImpl(Collections.<String, ModuleFactory>emptyMap(), lookupRegistry,
+                Collections.<String /* qName */, Map<String /* refName */, ModuleIdentifier>>emptyMap());
+    }
+
+    /**
+     * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
+     */
+    public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
+            LookupRegistry lookupRegistry, Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
+
+        ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldReadableRegistry;
+        Map<String, ModuleFactory> factories = extractFactoriesMap(currentlyRegisteredFactories);
+        return new ServiceReferenceRegistryImpl(factories, lookupRegistry, Collections.unmodifiableMap(old.refNames));
+    }
+
+    /**
+     * Copy back state to config registry after commit.
+     */
+    public static ServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry, LookupRegistry lookupRegistry) {
+        ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldWritableRegistry;
+        // even if factories do change, nothing in the mapping can change between transactions
+        return new ServiceReferenceRegistryImpl(old.factories, lookupRegistry, Collections.unmodifiableMap(old.refNames));
+    }
+
+    private static Map<String, ModuleFactory> extractFactoriesMap(Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
+        Map<String, ModuleFactory> result = new HashMap<>();
+        for (Entry<String, Entry<ModuleFactory, BundleContext>> entry : currentlyRegisteredFactories.entrySet()) {
+            result.put(entry.getKey(), entry.getValue().getKey());
+        }
+        return result;
+    }
+
+    private ServiceReferenceRegistryImpl(Map<String, ModuleFactory> factories, LookupRegistry lookupRegistry,
+                                         Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> refNamesToCopy) {
+        this.factories = factories;
+        this.lookupRegistry = lookupRegistry;
+        Map<String, Set<String /* QName */>> factoryNamesToQNames = new HashMap<>();
+        Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
+        Set<String /* qName */> allQNames = new HashSet<>();
+        for (Entry<String, ModuleFactory> entry : factories.entrySet()) {
+            if (entry.getKey().equals(entry.getValue().getImplementationName()) == false) {
+                logger.error("Possible error in code: Mismatch between supplied and actual name of {}", entry);
+                throw new IllegalArgumentException("Possible error in code: Mismatch between supplied and actual name of " + entry);
+            }
+            Set<ServiceInterfaceAnnotation> siAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(entry.getValue());
+            Set<String> qNames = new HashSet<>();
+            for (ServiceInterfaceAnnotation sia: siAnnotations) {
+                qNames.add(sia.value());
+            }
+            allAnnotations.addAll(siAnnotations);
+            allQNames.addAll(qNames);
+            factoryNamesToQNames.put(entry.getKey(), Collections.unmodifiableSet(qNames));
+        }
+        this.factoryNamesToQNames = Collections.unmodifiableMap(factoryNamesToQNames);
+        this.allQNames = Collections.unmodifiableSet(allQNames);
+        // fill namespacesToAnnotations
+        Map<String /* namespace */, Map<String /* localName */, ServiceInterfaceAnnotation>> namespacesToAnnotations =
+                new HashMap<>();
+        for (ServiceInterfaceAnnotation sia : allAnnotations) {
+            Map<String, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(sia.namespace());
+            if (ofNamespace == null) {
+                ofNamespace = new HashMap<>();
+                namespacesToAnnotations.put(sia.namespace(), ofNamespace);
+            }
+            if (ofNamespace.containsKey(sia.localName())) {
+                logger.error("Cannot construct namespacesToAnnotations map, conflict between local names in {}, offending local name: {}, map so far {}",
+                        sia.namespace(), sia.localName(), namespacesToAnnotations);
+                throw new IllegalArgumentException("Conflict between local names in " + sia.namespace() + " : " + sia.localName());
+            }
+            ofNamespace.put(sia.localName(), sia);
+        }
+        this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations);
+        // copy refNames
+        Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> deepCopy = new HashMap<>();
+        for (Entry<String, Map<String, ModuleIdentifier>> outerROEntry: refNamesToCopy.entrySet()) {
+            Map<String /* refName */, ModuleIdentifier> innerWritableMap = new HashMap<>();
+            deepCopy.put(outerROEntry.getKey(), innerWritableMap);
+            for (Entry<String, ModuleIdentifier> innerROEntry:  outerROEntry.getValue().entrySet()) {
+                innerWritableMap.put(innerROEntry.getKey(), innerROEntry.getValue());
+            }
+        }
+        this.refNames = deepCopy;
+        logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
+        logger.trace("refNames:{}", refNames);
+    }
+
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        lookupRegistry.checkConfigBeanExists(objectName);
+
+        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+        Set<String> serviceInterfaceAnnotations = factoryNamesToQNames.get(factoryName);
+        if (serviceInterfaceAnnotations == null) {
+            logger.error("Possible error in code: cannot find factory annotations of '{}' extracted from ON {} in {}",
+                    factoryName, objectName, factoryNamesToQNames);
+            throw new IllegalArgumentException("Cannot find factory with name " + factoryName);
+        }
+        return serviceInterfaceAnnotations;
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        Map<String /* localName */, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(namespace);
+        if (ofNamespace == null) {
+            logger.error("Cannot find namespace {} in {}", namespace, namespacesToAnnotations);
+            throw new IllegalArgumentException("Cannot find namespace " + namespace);
+        }
+        ServiceInterfaceAnnotation sia = ofNamespace.get(localName);
+        if (sia == null) {
+            logger.error("Cannot find local name {} in namespace {}, found only {}", localName, namespace, ofNamespace);
+            throw new IllegalArgumentException("Cannot find local name " + localName + " in namespace " + namespace);
+        }
+        return sia.value();
+    }
+
+
+
+    // reading:
+
+    @Override
+    public Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
+        Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
+        for (Entry<String /* qName */, Map<String, ModuleIdentifier>> outerEntry: refNames.entrySet()) {
+            String qName = outerEntry.getKey();
+            Map<String /* refName */, ObjectName> innerMap = new HashMap<>();
+            result.put(qName, innerMap);
+            for (Entry<String /* refName */, ModuleIdentifier> innerEntry: outerEntry.getValue().entrySet()) {
+                ModuleIdentifier moduleIdentifier = innerEntry.getValue();
+                ObjectName on;
+                on = getObjectName(moduleIdentifier);
+                innerMap.put(innerEntry.getKey(), on);
+            }
+        }
+        return result;
+    }
+
+    private ObjectName getObjectName(ModuleIdentifier moduleIdentifier) {
+        ObjectName on;
+        try {
+            on = lookupRegistry.lookupConfigBean(moduleIdentifier.getFactoryName(), moduleIdentifier.getInstanceName());
+        } catch (InstanceNotFoundException e) {
+            logger.error("Cannot find instance {}", moduleIdentifier);
+            throw new IllegalStateException("Cannot find instance " + moduleIdentifier, e);
+        }
+        return on;
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        Map<String, ModuleIdentifier> innerMap = refNames.get(serviceInterfaceName);
+        if (innerMap == null) {
+            logger.error("Cannot find qname {} in {}", serviceInterfaceName, refName);
+            throw new IllegalArgumentException("Cannot find " + serviceInterfaceName);
+        }
+        ModuleIdentifier moduleIdentifier = innerMap.get(refName);
+        if (moduleIdentifier == null) {
+            logger.error("Cannot find refName {} in {}, using qname {}", refName, innerMap, serviceInterfaceName);
+            throw new IllegalArgumentException("Cannot find module based on service reference " + refName);
+        }
+        return getObjectName(moduleIdentifier);
+    }
+
+    @Override
+    public  Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        Map<String, ModuleIdentifier> innerMap = refNames.get(serviceInterfaceName);
+        if (innerMap == null) {
+            logger.error("Cannot find qname {} in {}", serviceInterfaceName, refNames);
+            throw new IllegalArgumentException("Cannot find " + serviceInterfaceName);
+        }
+        Map<String /* refName */, ObjectName> result = new HashMap<>();
+        for (Entry<String/* refName */, ModuleIdentifier> entry: innerMap.entrySet()) {
+            ObjectName on = getObjectName(entry.getValue());
+            result.put(entry.getKey(), on);
+        }
+        return result;
+    }
+
+    // writing:
+
+    @Override
+    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName)  throws InstanceNotFoundException {
+        // make sure it is found
+        lookupRegistry.checkConfigBeanExists(objectName);
+        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+        // check that service interface name exist
+        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+        if (serviceInterfaceQNames == null) {
+            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName);
+            throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
+        }
+        // supplied serviceInterfaceName must exist in this collection
+        if (serviceInterfaceQNames.contains(serviceInterfaceName) == false) {
+            logger.error("Cannot find qname {} with factory name {}, found {}", serviceInterfaceName, factoryName, serviceInterfaceQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName + " within factory " + factoryName );
+        }
+        String instanceName = ObjectNameUtil.getInstanceName(objectName);
+        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
+        Map<String /* refName */, ModuleIdentifier> ofQName = refNames.get(serviceInterfaceName);
+        // might be null
+        if (ofQName == null) {
+            ofQName = new HashMap<>();
+            refNames.put(serviceInterfaceName, ofQName);
+        }
+        ofQName.put(refName, moduleIdentifier);
+    }
+
+    @Override
+    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
+        // is the qname known?
+        if (allQNames.contains(serviceInterfaceName) == false) {
+            logger.error("Cannot find qname {} in {}", serviceInterfaceName, allQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName);
+        }
+        Map<String, ModuleIdentifier> ofQName = refNames.get(serviceInterfaceName);
+        if (ofQName == null) {
+            return false;
+        }
+        return ofQName.remove(refName) != null;
+    }
+
+    @Override
+    public void removeAllServiceReferences() {
+        refNames.clear();
+    }
+
+    @Override
+    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
+        lookupRegistry.checkConfigBeanExists(objectName);
+        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+        // check that service interface name exist
+        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+        if (serviceInterfaceQNames == null) {
+            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName);
+            throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
+        }
+        String instanceName = ObjectNameUtil.getInstanceName(objectName);
+        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
+        boolean found = false;
+        for(String qName: serviceInterfaceQNames){
+            Map<String, ModuleIdentifier> ofQName = refNames.get(qName);
+            if (ofQName != null) {
+                for(Iterator<Entry<String, ModuleIdentifier>> it = ofQName.entrySet ().iterator(); it.hasNext();){
+                    Entry<String, ModuleIdentifier> next = it.next();
+                    if (next.getValue().equals(moduleIdentifier)) {
+                        found = true;
+                        it.remove();
+                    }
+                }
+            }
+        }
+        return found;
+    }
+
+    @Override
+    public String toString() {
+        return "ServiceReferenceRegistryImpl{" +
+                "refNames=" + refNames +
+                ", factoryNamesToQNames=" + factoryNamesToQNames +
+                '}';
+    }
+}
index 76cb64c..033f722 100644 (file)
@@ -7,17 +7,18 @@
  */
 package org.opendaylight.controller.config.manager.impl.util;
 
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+
+import javax.management.JMX;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
-import javax.management.JMX;
-
-import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
-import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
-import org.opendaylight.controller.config.spi.Module;
-
 public class InterfacesHelper {
 
     public static Set<Class<?>> getAllInterfaces(Class<?> clazz) {
@@ -32,16 +33,25 @@ public class InterfacesHelper {
             // get parent class
             clazz = clazz.getSuperclass();
         }
+        return getAllSuperInterfaces(toBeInspected);
+
+    }
+
+    private static Set<Class<?>> getAllSuperInterfaces(Set<Class<?>> ifcs) {
+        ifcs = new HashSet<>(ifcs); // create copy to modify
         // each interface can extend other interfaces
-        Set<Class<?>> inspected = new HashSet<>();
-        while (toBeInspected.size() > 0) {
-            Iterator<Class<?>> iterator = toBeInspected.iterator();
+        Set<Class<?>> result = new HashSet<>();
+        while (ifcs.size() > 0) {
+            Iterator<Class<?>> iterator = ifcs.iterator();
             Class<?> ifc = iterator.next();
             iterator.remove();
-            toBeInspected.addAll(Arrays.asList(ifc.getInterfaces()));
-            inspected.add(ifc);
+            if (ifc.isInterface() == false)  {
+                throw new IllegalArgumentException(ifc + " should be an interface");
+            }
+            ifcs.addAll(Arrays.asList(ifc.getInterfaces()));
+            result.add(ifc);
         }
-        return inspected;
+        return result;
     }
 
     /**
@@ -80,6 +90,18 @@ public class InterfacesHelper {
         return result;
     }
 
+    public static Set<Class<? extends AbstractServiceInterface>> getAllAbstractServiceClasses(Class<? extends Module> configBeanClass) {
+
+        Set<Class<? extends AbstractServiceInterface>> foundGeneratedSIClasses = new HashSet<>();
+        for (Class<?> clazz : getAllInterfaces(configBeanClass)) {
+            if (AbstractServiceInterface.class.isAssignableFrom(clazz) && AbstractServiceInterface.class.equals(clazz) == false) {
+                foundGeneratedSIClasses.add((Class<? extends AbstractServiceInterface>) clazz);
+            }
+        }
+        return getAllAbstractServiceInterfaceClasses(foundGeneratedSIClasses);
+    }
+
+
     /**
      * Get OSGi registration types under which config bean instance should be
      * registered. This is specified in
@@ -98,4 +120,37 @@ public class InterfacesHelper {
         return result;
     }
 
+
+    public static Set<ServiceInterfaceAnnotation> getServiceInterfaceAnnotations(ModuleFactory factory) {
+        Set<Class<? extends AbstractServiceInterface>> implementedServiceIntefaces = Collections.unmodifiableSet(factory.getImplementedServiceIntefaces());
+        return getServiceInterfaceAnnotations(implementedServiceIntefaces);
+    }
+
+    private static Set<ServiceInterfaceAnnotation> getServiceInterfaceAnnotations(Set<Class<? extends AbstractServiceInterface>> implementedServiceIntefaces) {
+        Set<Class<? extends AbstractServiceInterface>> inspected = getAllAbstractServiceInterfaceClasses(implementedServiceIntefaces);
+        Set<ServiceInterfaceAnnotation> result = new HashSet<>();
+        // SIs can form hierarchies, inspect superclass until it does not extend AbstractSI
+        for (Class<?> clazz : inspected) {
+            ServiceInterfaceAnnotation annotation = clazz.getAnnotation(ServiceInterfaceAnnotation.class);
+            if (annotation != null) {
+                result.add(annotation);
+            }
+        }
+        return result;
+    }
+
+    static Set<Class<? extends AbstractServiceInterface>> getAllAbstractServiceInterfaceClasses(
+            Set<Class<? extends AbstractServiceInterface>> directlyImplementedAbstractSIs) {
+
+        Set<Class<?>> allInterfaces = getAllSuperInterfaces((Set) directlyImplementedAbstractSIs);
+        Set<Class<? extends AbstractServiceInterface>> result = new HashSet<>();
+        for(Class<?> ifc: allInterfaces){
+            if (AbstractServiceInterface.class.isAssignableFrom(ifc) &&
+                    ifc.equals(AbstractServiceInterface.class) == false) {
+                result.add((Class<? extends AbstractServiceInterface>) ifc);
+            }
+
+        }
+        return result;
+    }
 }
index d23b5ca..672f150 100644 (file)
@@ -13,6 +13,7 @@ import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
@@ -107,4 +108,9 @@ public class ClassBasedModuleFactory implements ModuleFactory {
     public Set<Module> getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) {
         return new HashSet<Module>();
     }
+
+    @Override
+    public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+        return InterfacesHelper.getAllAbstractServiceClasses(configBeanClass);
+    }
 }
index 22a9590..43c75ef 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.collect.Sets;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator;
@@ -61,13 +62,22 @@ public class ConfigTransactionControllerImplTest extends
                 ManagementFactory.getPlatformMBeanServer());
         transactionsMBeanServer = MBeanServerFactory.createMBeanServer();
         Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories = new HashMap<>();
-        TransactionJMXRegistrator jmxRegistrator123 = baseJMXRegistrator
-                .createTransactionJMXRegistrator(transactionName123);
+
+        ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier(transactionName123), new TransactionJMXRegistratorFactory() {
+            @Override
+            public TransactionJMXRegistrator create() {
+                return baseJMXRegistrator.createTransactionJMXRegistrator(transactionName123);
+            }
+        });
+
+        ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+                ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(), txLookupRegistry, currentlyRegisteredFactories);
+
 
         testedTxController = new ConfigTransactionControllerImpl(
-                transactionName123, jmxRegistrator123, 1, 1,
+                txLookupRegistry, 1, 1,
                 currentlyRegisteredFactories, transactionsMBeanServer,
-                ManagementFactory.getPlatformMBeanServer(), false);
+                ManagementFactory.getPlatformMBeanServer(), false, writableRegistry);
         TransactionModuleJMXRegistrator transactionModuleJMXRegistrator123 = testedTxController
                 .getTxModuleJMXRegistrator();
         transactionModuleJMXRegistrator123.registerMBean(
index cf6ed18..75b0414 100644 (file)
@@ -97,7 +97,8 @@ public class AnnotationsTest {
     static final String SIMPLE = "simple";
     static final String SUBCLASS2 = "subclass2";
 
-    @ServiceInterfaceAnnotation(value = SIMPLE, osgiRegistrationType = Executor.class)
+    @ServiceInterfaceAnnotation(value = SIMPLE, osgiRegistrationType = Executor.class,
+    namespace = "ns", revision = "rev", localName = SIMPLE)
     static interface SimpleSI extends AbstractServiceInterface {
 
     }
@@ -161,7 +162,9 @@ public class AnnotationsTest {
 
     }
 
-    @ServiceInterfaceAnnotation(value = SUBCLASS2, osgiRegistrationType = ExecutorService.class)
+    @ServiceInterfaceAnnotation(value = SUBCLASS2, osgiRegistrationType = ExecutorService.class,
+    namespace = "ns", revision = "rev", localName = SUBCLASS2)
+
     static interface SubSI2 extends SubSI {
 
     }
index 9a5452a..22ea528 100644 (file)
@@ -9,11 +9,15 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.HashSet;
 import java.util.Set;
 
 import javax.management.MXBean;
 
 import org.junit.Test;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingScheduledThreadPoolServiceInterface;
+import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.yangtools.concepts.Identifiable;
 
@@ -60,4 +64,17 @@ public class InterfacesHelperTest {
         assertEquals(expected, InterfacesHelper.getMXInterfaces(SubClass.class));
     }
 
+    @Test
+    public void testGetAllAbstractServiceInterfaceClasses(){
+        Class<? extends AbstractServiceInterface> clazz = TestingScheduledThreadPoolServiceInterface.class;
+        Set<Class<? extends AbstractServiceInterface>> input = new HashSet<>();
+        input.add(clazz);
+        Set<Class<? extends AbstractServiceInterface>> result = InterfacesHelper.getAllAbstractServiceInterfaceClasses(input);
+
+        Set<Class<?>> expected = Sets.newHashSet((Class<?>) TestingScheduledThreadPoolServiceInterface.class,
+                TestingThreadPoolServiceInterface.class
+                );
+        assertEquals(expected, result);
+    }
+
 }
index 4fd2f5f..9674a11 100644 (file)
@@ -11,7 +11,8 @@ import javax.management.ObjectName;
 
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 
-@ServiceInterfaceAnnotation(value = TestingParallelAPSPConfigMXBean.NAME, osgiRegistrationType = TestingAPSP.class)
+@ServiceInterfaceAnnotation(value = TestingParallelAPSPConfigMXBean.NAME, osgiRegistrationType = TestingAPSP.class,
+namespace = "namespace", revision = "rev", localName = TestingParallelAPSPConfigMXBean.NAME)
 public interface TestingParallelAPSPConfigMXBean {
 
     static final String NAME = "apsp";
index 3adf114..50a5879 100644 (file)
@@ -18,6 +18,7 @@ import org.osgi.framework.BundleContext;
 
 import javax.annotation.concurrent.ThreadSafe;
 import javax.management.ObjectName;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -69,4 +70,9 @@ public class TestingParallelAPSPModuleFactory implements ModuleFactory {
     public Set<Module> getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext context) {
         return new HashSet<Module>();
     }
+
+    @Override
+    public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+        return Collections.emptySet();
+    }
 }
index 2e10478..e5306a4 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool;
 
+import com.google.common.collect.Sets;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
@@ -18,16 +19,16 @@ import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
 
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 public class TestingScheduledThreadPoolModuleFactory implements ModuleFactory {
     public static final String NAME = "scheduled";
 
-    private static List<Class<? extends TestingThreadPoolServiceInterface>> ifc = Arrays
-            .asList(TestingScheduledThreadPoolServiceInterface.class, TestingThreadPoolServiceInterface.class);
+    private static Set<Class<? extends AbstractServiceInterface>> ifc = Collections.unmodifiableSet(Sets.newHashSet(
+            (Class<? extends AbstractServiceInterface>) TestingScheduledThreadPoolServiceInterface.class,
+                    TestingThreadPoolServiceInterface.class));
 
     @Override
     public boolean isModuleImplementingServiceInterface(
@@ -70,4 +71,11 @@ public class TestingScheduledThreadPoolModuleFactory implements ModuleFactory {
     public Set<Module> getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) {
         return new HashSet<Module>();
     }
+
+    @Override
+    public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+        return ifc;
+    }
+
+
 }
index ab1b6bd..5c30d1e 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.controller.config.manager.testingservices.seviceinterfa
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingModifiableThreadPoolIfc;
 
-@ServiceInterfaceAnnotation(value = "modifiable-threadpool", osgiRegistrationType = TestingModifiableThreadPoolIfc.class)
+@ServiceInterfaceAnnotation(value = "fqn:modifiable-threadpool", osgiRegistrationType = TestingModifiableThreadPoolIfc.class,
+        namespace = "foo",  revision = "bar", localName = "modifiable-threadpool")
 public interface ModifiableThreadPoolServiceInterface extends
         TestingThreadPoolServiceInterface {
 }
index e4e388c..5ddc189 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.controller.config.manager.testingservices.seviceinterfa
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolIfc;
 
-@ServiceInterfaceAnnotation(value = "threadpool-scheduled", osgiRegistrationType = TestingScheduledThreadPoolIfc.class)
+@ServiceInterfaceAnnotation(value = "threadpool-scheduled", osgiRegistrationType = TestingScheduledThreadPoolIfc.class,
+    namespace = "ns", revision = "rev", localName = "threadpool-scheduled")
 public interface TestingScheduledThreadPoolServiceInterface extends
         TestingThreadPoolServiceInterface {
 }
index fd5ab17..91a4cff 100644 (file)
@@ -11,7 +11,8 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
 
-@ServiceInterfaceAnnotation(value = "testing-threadpool", osgiRegistrationType = TestingThreadPoolIfc.class)
+@ServiceInterfaceAnnotation(value = "testing-threadpool", osgiRegistrationType = TestingThreadPoolIfc.class,
+    namespace = "ns", revision = "foo", localName = "bar")
 public interface TestingThreadPoolServiceInterface extends
         AbstractServiceInterface {
 }
index cf05e44..b749ea7 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.threadpool;
 
+import com.google.common.collect.Sets;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
@@ -18,15 +19,16 @@ import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
 
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 public class TestingFixedThreadPoolModuleFactory implements ModuleFactory {
     public static final String NAME = "fixed";
-    private static List<Class<? extends TestingThreadPoolServiceInterface>> ifc = Arrays
-            .asList(ModifiableThreadPoolServiceInterface.class, TestingThreadPoolServiceInterface.class);
+
+    private static Set<Class<? extends AbstractServiceInterface>> ifc = Collections.unmodifiableSet(Sets.newHashSet(
+            (Class<? extends AbstractServiceInterface>) ModifiableThreadPoolServiceInterface.class,
+            TestingThreadPoolServiceInterface.class));
 
     @Override
     public String getImplementationName() {
@@ -71,4 +73,9 @@ public class TestingFixedThreadPoolModuleFactory implements ModuleFactory {
     public Set<Module> getDefaultModules(DependencyResolverFactory dependencyResolverFactory, BundleContext bundleContext) {
         return new HashSet<Module>();
     }
+
+    @Override
+    public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+        return ifc;
+    }
 }
index 3a1efae..4ecc7c3 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.util;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.management.AttributeNotFoundException;
@@ -28,7 +29,7 @@ import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 
 public class ConfigRegistryJMXClient implements ConfigRegistryClient {
-    private final ConfigRegistryMXBean configRegistryProxy;
+    private final ConfigRegistryMXBean configRegistryMXBeanProxy;
     private final ObjectName configRegistryON;
     private final MBeanServer configMBeanServer;
 
@@ -40,7 +41,7 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
         if (!(searchResult.size() == 1)) {
             throw new IllegalStateException("Config registry not found");
         }
-        configRegistryProxy = JMX.newMXBeanProxy(configMBeanServer, configRegistryON, ConfigRegistryMXBean.class,
+        configRegistryMXBeanProxy = JMX.newMXBeanProxy(configMBeanServer, configRegistryON, ConfigRegistryMXBean.class,
                 false);
     }
 
@@ -61,7 +62,7 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     @Override
     public ConfigTransactionJMXClient getConfigTransactionClient(
             ObjectName objectName) {
-        return new ConfigTransactionJMXClient(configRegistryProxy, objectName,
+        return new ConfigTransactionJMXClient(configRegistryMXBeanProxy, objectName,
                 configMBeanServer);
     }
 
@@ -75,18 +76,18 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
 
     @Override
     public ObjectName beginConfig() {
-        return configRegistryProxy.beginConfig();
+        return configRegistryMXBeanProxy.beginConfig();
     }
 
     @Override
     public CommitStatus commitConfig(ObjectName transactionControllerON)
             throws ConflictingVersionException, ValidationException {
-        return configRegistryProxy.commitConfig(transactionControllerON);
+        return configRegistryMXBeanProxy.commitConfig(transactionControllerON);
     }
 
     @Override
     public List<ObjectName> getOpenConfigs() {
-        return configRegistryProxy.getOpenConfigs();
+        return configRegistryMXBeanProxy.getOpenConfigs();
     }
 
     @Override
@@ -101,45 +102,75 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
 
     @Override
     public Set<String> getAvailableModuleNames() {
-        return configRegistryProxy.getAvailableModuleNames();
+        return configRegistryMXBeanProxy.getAvailableModuleNames();
     }
 
     @Override
     public boolean isHealthy() {
-        return configRegistryProxy.isHealthy();
+        return configRegistryMXBeanProxy.isHealthy();
     }
 
     @Override
     public Set<ObjectName> lookupConfigBeans() {
-        return configRegistryProxy.lookupConfigBeans();
+        return configRegistryMXBeanProxy.lookupConfigBeans();
     }
 
     @Override
     public Set<ObjectName> lookupConfigBeans(String moduleName) {
-        return configRegistryProxy.lookupConfigBeans(moduleName);
+        return configRegistryMXBeanProxy.lookupConfigBeans(moduleName);
     }
 
     @Override
     public Set<ObjectName> lookupConfigBeans(String moduleName,
             String instanceName) {
-        return configRegistryProxy.lookupConfigBeans(moduleName, instanceName);
+        return configRegistryMXBeanProxy.lookupConfigBeans(moduleName, instanceName);
     }
 
     @Override
     public ObjectName lookupConfigBean(String moduleName, String instanceName)
             throws InstanceNotFoundException {
-        return configRegistryProxy.lookupConfigBean(moduleName, instanceName);
+        return configRegistryMXBeanProxy.lookupConfigBean(moduleName, instanceName);
     }
 
     @Override
     public Set<ObjectName> lookupRuntimeBeans() {
-        return configRegistryProxy.lookupRuntimeBeans();
+        return configRegistryMXBeanProxy.lookupRuntimeBeans();
     }
 
     @Override
     public Set<ObjectName> lookupRuntimeBeans(String ifcName,
             String instanceName) {
-        return configRegistryProxy.lookupRuntimeBeans(ifcName, instanceName);
+        return configRegistryMXBeanProxy.lookupRuntimeBeans(ifcName, instanceName);
+    }
+
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        configRegistryMXBeanProxy.checkConfigBeanExists(objectName);
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        return configRegistryMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    }
+
+    @Override
+    public Map<String, Map<String, ObjectName>> getServiceMapping() {
+        return configRegistryMXBeanProxy.getServiceMapping();
+    }
+
+    @Override
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    }
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        return configRegistryMXBeanProxy.lookupServiceInterfaceNames(objectName);
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        return configRegistryMXBeanProxy.getServiceInterfaceName(namespace, localName);
     }
 
     @Override
index 548c0e9..bd6f6fa 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.util;
 
+import java.util.Map;
 import java.util.Set;
 
 import javax.management.Attribute;
@@ -26,19 +27,19 @@ import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXB
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 
 public class ConfigTransactionJMXClient implements ConfigTransactionClient {
-    private final ConfigRegistryMXBean configTransactionManagerProxy;
+    private final ConfigRegistryMXBean configRegistryMXBeanProxy;
     private final ObjectName configTransactionControllerON;
-    private final ConfigTransactionControllerMXBean configControllerProxy;
+    private final ConfigTransactionControllerMXBean configTransactionControllerMXBeanProxy;
     private final MBeanServer configMBeanServer;
 
     public ConfigTransactionJMXClient(
-            ConfigRegistryMXBean configTransactionManagerProxy,
+            ConfigRegistryMXBean configRegistryMXBeanProxy,
             ObjectName configTransactionControllerON,
             MBeanServer configMBeanServer) {
         this.configMBeanServer = configMBeanServer;
-        this.configTransactionManagerProxy = configTransactionManagerProxy;
+        this.configRegistryMXBeanProxy = configRegistryMXBeanProxy;
         this.configTransactionControllerON = configTransactionControllerON;
-        this.configControllerProxy = JMX.newMXBeanProxy(configMBeanServer,
+        this.configTransactionControllerMXBeanProxy = JMX.newMXBeanProxy(configMBeanServer,
                 configTransactionControllerON,
                 ConfigTransactionControllerMXBean.class);
     }
@@ -54,7 +55,7 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     @Override
     public CommitStatus commit() throws ConflictingVersionException,
             ValidationException {
-        return configTransactionManagerProxy
+        return configRegistryMXBeanProxy
                 .commitConfig(configTransactionControllerON);
     }
 
@@ -73,13 +74,13 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     @Override
     public ObjectName createModule(String moduleName, String instanceName)
             throws InstanceAlreadyExistsException {
-        return configControllerProxy.createModule(moduleName, instanceName);
+        return configTransactionControllerMXBeanProxy.createModule(moduleName, instanceName);
     }
 
     @Override
     public void destroyModule(ObjectName objectName)
             throws InstanceNotFoundException {
-        configControllerProxy.destroyModule(objectName);
+        configTransactionControllerMXBeanProxy.destroyModule(objectName);
     }
 
     @Override
@@ -91,12 +92,12 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
 
     @Override
     public void abortConfig() {
-        configControllerProxy.abortConfig();
+        configTransactionControllerMXBeanProxy.abortConfig();
     }
 
     @Override
     public void validateConfig() throws ValidationException {
-        configControllerProxy.validateConfig();
+        configTransactionControllerMXBeanProxy.validateConfig();
     }
 
     @Override
@@ -121,12 +122,12 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
 
     @Override
     public String getTransactionName() {
-        return configControllerProxy.getTransactionName();
+        return configTransactionControllerMXBeanProxy.getTransactionName();
     }
 
     @Override
     public Set<String> getAvailableModuleNames() {
-        return configControllerProxy.getAvailableModuleNames();
+        return configTransactionControllerMXBeanProxy.getAvailableModuleNames();
     }
 
     @Override
@@ -136,27 +137,77 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
 
     @Override
     public Set<ObjectName> lookupConfigBeans() {
-        return configControllerProxy.lookupConfigBeans();
+        return configTransactionControllerMXBeanProxy.lookupConfigBeans();
     }
 
     @Override
     public Set<ObjectName> lookupConfigBeans(String moduleName) {
-        return configControllerProxy.lookupConfigBeans(moduleName);
+        return configTransactionControllerMXBeanProxy.lookupConfigBeans(moduleName);
     }
 
     @Override
     public ObjectName lookupConfigBean(String moduleName, String instanceName)
             throws InstanceNotFoundException {
-        return configControllerProxy.lookupConfigBean(moduleName, instanceName);
+        return configTransactionControllerMXBeanProxy.lookupConfigBean(moduleName, instanceName);
     }
 
     @Override
     public Set<ObjectName> lookupConfigBeans(String moduleName,
             String instanceName) {
-        return configControllerProxy
+        return configTransactionControllerMXBeanProxy
                 .lookupConfigBeans(moduleName, instanceName);
     }
 
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        configTransactionControllerMXBeanProxy.checkConfigBeanExists(objectName);
+    }
+
+    @Override
+    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
+        configTransactionControllerMXBeanProxy.saveServiceReference(serviceInterfaceName,refName,objectName);
+    }
+
+    @Override
+    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
+        return configTransactionControllerMXBeanProxy.removeServiceReference(serviceInterfaceName, refName);
+    }
+
+    @Override
+    public void removeAllServiceReferences() {
+        configTransactionControllerMXBeanProxy.removeAllServiceReferences();
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        return configTransactionControllerMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    }
+
+    @Override
+    public Map<String, Map<String, ObjectName>> getServiceMapping() {
+        return configTransactionControllerMXBeanProxy.getServiceMapping();
+    }
+
+    @Override
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    }
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        return configTransactionControllerMXBeanProxy.lookupServiceInterfaceNames(objectName);
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        return configTransactionControllerMXBeanProxy.getServiceInterfaceName(namespace, localName);
+    }
+
+    @Override
+    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
+        return configTransactionControllerMXBeanProxy.removeServiceReferences(objectName);
+    }
+
     @Override
     public void validateBean(ObjectName configBeanON)
             throws ValidationException {
index f29f0e0..9d55f8d 100644 (file)
@@ -8,8 +8,10 @@
 package org.opendaylight.controller.config.util.jolokia;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 
 import org.jolokia.client.request.J4pExecRequest;
@@ -24,6 +26,7 @@ import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 
+@Deprecated
 public class ConfigRegistryJolokiaClient extends ListableJolokiaClient
         implements ConfigRegistryClient {
 
@@ -136,4 +139,35 @@ public class ConfigRegistryJolokiaClient extends ListableJolokiaClient
     public Object getAttributeCurrentValue(ObjectName on, String attributeName) {
         throw new UnsupportedOperationException();
     }
+
+    // TODO: implement or deprecate
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, Map<String, ObjectName>> getServiceMapping() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        throw new UnsupportedOperationException();
+    }
 }
index f4824cd..834e9c6 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.config.util.jolokia;
 
 import java.util.Map;
+import java.util.Set;
 
 import javax.management.Attribute;
 import javax.management.AttributeNotFoundException;
@@ -25,6 +26,7 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.util.AttributeEntry;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 
+@Deprecated
 public class ConfigTransactionJolokiaClient extends ListableJolokiaClient
         implements ConfigTransactionClient {
 
@@ -162,4 +164,54 @@ public class ConfigTransactionJolokiaClient extends ListableJolokiaClient
         throw new UnsupportedOperationException();
     }
 
+    // TODO: implement or deprecate
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeAllServiceReferences() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, Map<String, ObjectName>> getServiceMapping() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
 }
index 6277f6a..321d23f 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.controller.config.api.ValidationException.ExceptionMessa
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.util.AttributeEntry;
 
+
 abstract class ListableJolokiaClient {
     protected final J4pClient j4pClient;
     protected final String url;
index 0749204..52e9345 100644 (file)
@@ -12,6 +12,7 @@ import static org.junit.Assert.fail;
 
 import java.lang.management.ManagementFactory;
 import java.lang.reflect.Method;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -69,9 +70,9 @@ public class LookupTest {
                 ManagementFactory.getPlatformMBeanServer());
         jolokiaTransactionClient = new ConfigTransactionJolokiaClient(
                 jolokiaURL, testingTransactionControllerON, null);
-        lookupProvidersToClients = ImmutableMap
-                .of(testingRegistry, Sets.newHashSet(jmxRegistryClient, jolokiaRegistryClient),
-                        testingTransactionController, Sets.newHashSet(jmxTransactionClient, jolokiaTransactionClient));
+        HashSet<ConfigRegistryClient> registryClients = Sets.newHashSet(jmxRegistryClient, jolokiaRegistryClient);
+        HashSet<ConfigTransactionClient> configTransactionClients = Sets.newHashSet(jmxTransactionClient, jolokiaTransactionClient);
+        lookupProvidersToClients = ImmutableMap.of((LookupRegistry) testingRegistry, registryClients,                testingTransactionController, configTransactionClients);
     }
 
     @After
index d4ae42d..ba62627 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.controller.config.util;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.management.InstanceNotFoundException;
@@ -143,4 +144,33 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
         }
     }
 
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, Map<String, ObjectName>> getServiceMapping() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        throw new UnsupportedOperationException();
+    }
 }
index 67e31b0..0a845e1 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.util;
 
+import java.util.Map;
 import java.util.Set;
 
 import javax.management.InstanceAlreadyExistsException;
@@ -109,4 +110,54 @@ public class TestingConfigTransactionController implements
             return null;
         }
     }
+
+    @Override
+    public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void removeAllServiceReferences() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, Map<String, ObjectName>> getServiceMapping() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getServiceInterfaceName(String namespace, String localName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
 }
index 5ec359e..59368e8 100644 (file)
@@ -49,10 +49,13 @@ public class Annotation {
         Preconditions.checkNotNull(exportedClassName,
                 "Cannot create annotation from null exportedClassName");
 
-        List<Parameter> params = Lists.newArrayList(new Parameter("value",
-                q(qname.getLocalName())));
-        params.add(new Parameter("osgiRegistrationType", exportedClassName
-                + ".class"));
+        List<Parameter> params = Lists.newArrayList(new Parameter("value", q(qname.toString())));
+        params.add(new Parameter("osgiRegistrationType", exportedClassName + ".class"));
+
+        params.add(new Parameter("namespace", q(qname.getNamespace().toString())));
+        params.add(new Parameter("revision", q(qname.getFormattedRevision())));
+        params.add(new Parameter("localName", q(qname.getLocalName())));
+
         return new Annotation(
                 ServiceInterfaceAnnotation.class.getCanonicalName(), params);
     }
index a331e4e..37fd05b 100644 (file)
@@ -6,12 +6,14 @@ package ${packageName};
 {
 
     public static final java.lang.String NAME = "${globallyUniqueName}";
-    private static final java.util.Set<Class<? extends ${abstractServiceInterfaceType}>> serviceIfcs = new java.util.HashSet<Class<? extends ${abstractServiceInterfaceType}>>();
+    private static final java.util.Set<Class<? extends ${abstractServiceInterfaceType}>> serviceIfcs;
     <#if providedServices??>
     static {
+        java.util.Set<Class<? extends ${abstractServiceInterfaceType}>> serviceIfcs2 = new java.util.HashSet<Class<? extends ${abstractServiceInterfaceType}>>();
         <#list providedServices as refId>
-        serviceIfcs.add(${refId});
+        serviceIfcs2.add(${refId});
         </#list>
+        serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2);
     }
     </#if>
 
@@ -25,6 +27,12 @@ package ${packageName};
         return false;
     }
 
+    @Override
+    public java.util.Set<Class<? extends ${abstractServiceInterfaceType}>> getImplementedServiceIntefaces() {
+        return serviceIfcs;
+    }
+
+
     @Override
     public ${moduleType} createModule(String instanceName, ${dependencyResolverType} dependencyResolver, ${bundleContextType} bundleContext) {
         return instantiateModule(instanceName, dependencyResolver, bundleContext);
index 1945cac..3ef4066 100644 (file)
@@ -438,11 +438,11 @@ public class JMXGeneratorTest extends AbstractGeneratorTest {
                 "public static final java.lang.String NAME=\"threadfactory-naming\"");
         assertDeclaredField(
                 fieldDeclarations,
-                "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs=new java.util.HashSet<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>>()");
+                "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs");
 
         assertEquals(2, fieldDeclarations.size());
 
-        assertFactoryMethods(visitor.methods, 8);
+        assertFactoryMethods(visitor.methods, 9);
         assertEquals("Incorrenct number of generated method descriptions", 0,
                 visitor.methodDescriptions.size());
         assertEquals("Incorrenct number of generated method javadoc", 0,

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.