Merge "removed parent dependency on pax-exam-container-native"
authorEd Warnicke <eaw@cisco.com>
Thu, 12 Dec 2013 14:40:11 +0000 (14:40 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 12 Dec 2013 14:40:11 +0000 (14:40 +0000)
106 files changed:
opendaylight/commons/controller-maven-plugin/pom.xml [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/AbstractControllerMojo.java [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StartControllerMojo.java [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StopControllerMojo.java [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JavaProcess.java [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JpsProcessMonitor.java [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/ProcessMonitor.java [new file with mode: 0644]
opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/VMProcessMonitor.java [new file with mode: 0644]
opendaylight/commons/opendaylight/pom.xml
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/dependencyresolver/DependencyResolverImpl.java
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/AbstractConfigWithJolokiaTest.java [deleted file]
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/ConfigTransactionManagerImplTest.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/parallelapsp/test/AbstractParallelAPSPTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.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-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java
opendaylight/config/config-util/pom.xml
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 [deleted file]
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java [deleted file]
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java [deleted file]
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/ConfigRegistryClientsTest.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/ConfigTransactionClientsTest.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/JolokiaHelper.java [deleted file]
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/config-util/src/test/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClientTest.java [deleted file]
opendaylight/config/pom.xml
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
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/opendaylight/runsanity.bat [deleted file]
opendaylight/distribution/opendaylight/runsanity.sh [deleted file]
opendaylight/distribution/opendaylight/src/assemble/bin.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/01-md-sal.conf
opendaylight/distribution/opendaylight/src/main/resources/run.bat
opendaylight/distribution/sanitytest/pom.xml
opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/distribution/Sanity.java [deleted file]
opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/sanitytest/internal/Activator.java [deleted file]
opendaylight/distribution/sanitytest/src/test/java/org/opendaylight/controller/distribution/test/SanityIT.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributesConstants.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectNameAttributeMappingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectNameAttributeResolvingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfigElementResolved.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Services.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/AbstractEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/DeleteEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigXmlParser.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditStrategyType.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/MergeEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/NoneEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/RemoveEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationProvider.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/transactions/TransactionProvider.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/ServiceTrackerTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfigTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/ReplaceEditConfigStrategyTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_addServiceName.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_merge_threadfactory.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_none.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_remove.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpc.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml
pom.xml

diff --git a/opendaylight/commons/controller-maven-plugin/pom.xml b/opendaylight/commons/controller-maven-plugin/pom.xml
new file mode 100644 (file)
index 0000000..1ab4e70
--- /dev/null
@@ -0,0 +1,83 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.1-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <artifactId>controller-maven-plugin</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>maven-plugin</packaging>
+
+  <name>controller-maven-plugin</name>
+  <description>Maven Plugin for controlling the launch of the controller.</description>
+  <url>http://maven.apache.org</url>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <!-- controller mojos depend on the api module -->
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-plugin-api</artifactId>
+      <version>2.0</version>
+    </dependency>
+    <dependency>
+      <!-- controller mojos use the annotations defined in this module -->
+      <groupId>org.apache.maven.plugin-tools</groupId>
+      <artifactId>maven-plugin-annotations</artifactId>
+      <version>3.2</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <!-- needed for handling processes -->
+      <groupId>com.sun</groupId>
+      <artifactId>tools</artifactId>
+      <scope>system</scope>
+      <version>7</version>
+      <systemPath>${java.home}/../lib/tools.jar</systemPath>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <!-- plugin builder -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-plugin-plugin</artifactId>
+        <version>3.2</version>
+        <configuration>
+          <goalPrefix>controller-maven-plugin</goalPrefix>
+          <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+        </configuration>
+        <executions>
+          <execution>
+            <id>mojo-descriptor</id>
+            <goals>
+              <goal>descriptor</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>help-goal</id>
+            <goals>
+              <goal>helpmojo</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/AbstractControllerMojo.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/AbstractControllerMojo.java
new file mode 100644 (file)
index 0000000..39ca71c
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * 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.maven.plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Parameter;
+
+import org.opendaylight.controller.maven.plugin.util.JavaProcess;
+import org.opendaylight.controller.maven.plugin.util.ProcessMonitor;
+
+/**
+ * Base controller mojo which handles common operations
+ */
+public abstract class AbstractControllerMojo extends AbstractMojo {
+    public static final String OS_NAME = System.getProperty("os.name");
+    public static final boolean WIN = OS_NAME.toUpperCase().contains("WINDOWS");
+    public static final String JAVA_HOME = "JAVA_HOME";
+    public static final boolean skip = Boolean.getBoolean("controller.startup.skip");
+    public static final String MAIN_CLASS = "org.eclipse.equinox.launcher.Main";
+    public static final String CTRL_PROP = "opendaylight.controller";
+
+    /**
+     * The home directory where controller is installed
+     */
+    @Parameter( required = false )
+    protected File controllerHome;
+
+    /**
+     * The address on which controller is listening
+     */
+    @Parameter( defaultValue = "localhost")
+    protected String controllerHost;
+
+    /**
+     * The admin web port
+     */
+    @Parameter( defaultValue = "8080")
+    protected int controllerWebPort;
+
+    /**
+     * The openflow port
+     */
+    @Parameter( defaultValue = "6633")
+    protected int controllerOFPort;
+
+    /**
+     * Additional environment variables passed when starting the controller
+     * process.
+     */
+    @Parameter(required = false)
+    protected Properties controllerShellVariables;
+
+    /**
+     * The script name to invoke
+     */
+    @Parameter(required = false)
+    protected String controllerStartScriptName;
+
+    /**
+     * The username
+     */
+    @Parameter(required = false)
+    protected String controllerUsername;
+
+    /**
+     * The password
+     */
+    @Parameter(required = false)
+    protected String controllerPassword;
+
+    /**
+     * pidFile location
+     */
+    @Parameter(required = false)
+    protected File pidFile;
+
+    protected final ProcessMonitor procMon = ProcessMonitor.load();
+
+    public abstract void start() throws MojoExecutionException, MojoFailureException;
+
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        if (skip) return;
+        validateArgs();
+        start();
+    }
+
+    protected URL getWebUrl() {
+      try {
+        return new URL("http", controllerHost, controllerWebPort, "/");
+      } catch (MalformedURLException e) {
+        throw new IllegalArgumentException(
+            "controller host:port is Malformed: " + controllerHost + " " + controllerWebPort, e);
+      }
+
+    }
+
+    protected void validateArgs() throws IllegalArgumentException {
+        // System property and environment variable override the default setting
+        String odlHome = System.getProperty("controllerHome");
+        if (odlHome != null) {
+          controllerHome = new File(odlHome);
+        }
+        if (controllerHome == null) {
+            getLog().error("controllerHome cannot be determined from controllerHome "
+                + "property or ONE_HOME env variable");
+            throw new IllegalArgumentException("controllerHome cannot be determined.");
+        }
+        if (!controllerHome.exists()) {
+            throw new IllegalArgumentException(
+                    "controllerHome does not exist: " + controllerHome);
+        }
+       if (controllerUsername == null) {
+            controllerUsername = System.getProperty("controllerUsername");
+        }
+        if (controllerPassword == null) {
+            controllerPassword= System.getProperty("controllerPassword");
+        }
+        URL u = getWebUrl();
+        getLog().info("Controller Home       : " + controllerHome);
+        getLog().info("Controller Url        : " + u);
+        getLog().info("Controller credentials: " + controllerUsername
+                + "/" + controllerPassword);
+    }
+
+    protected Process invokeScript(List<String> args, String log)
+            throws MojoFailureException, MojoExecutionException
+    {
+        ProcessBuilder pb = new ProcessBuilder();
+        List<String> cmd = new ArrayList<String>();
+        cmd.add(getScript());
+        if (args != null) {
+            for (String s : args) {
+                // on windows args containing equals symbols need to be quoted
+                if (WIN && s.contains("=") && !s.startsWith("\"")) {
+                  cmd.add("\"" + s + "\"");
+                } else {
+                  cmd.add(s);
+                }
+            }
+        }
+        pb.command(cmd);
+        pb.directory(controllerHome);
+        pb.redirectErrorStream(true);
+        pb.inheritIO();
+        Map<String,String> env = pb.environment();
+        if (controllerShellVariables != null) {
+            for (Enumeration e = controllerShellVariables.propertyNames(); e.hasMoreElements();) {
+                String n = (String) e.nextElement();
+                env.put(n, controllerShellVariables.getProperty(n));
+            }
+        }
+        String jh = env.get(JAVA_HOME);
+        if (jh == null) env.put(JAVA_HOME, System.getProperty("java.home"));
+        try {
+            getLog().info("Invoking process " + pb.command());
+            return pb.start();
+        } catch (IOException e) {
+            throw new MojoExecutionException(e.getMessage());
+        }
+    }
+
+    private String getScript() throws MojoFailureException {
+        File script = null;
+        if (controllerStartScriptName != null && !"".equals(controllerStartScriptName) ) {
+            script = new File(controllerStartScriptName);
+            if (!script.exists()) {
+                // try relative path
+                script = new File(controllerHome, controllerStartScriptName);
+            }
+            if (script.exists()) return script.getAbsolutePath();
+            throw new MojoFailureException("Script not found: " + controllerStartScriptName);
+        }
+        // try default
+        script = new File(controllerHome, "run." + (WIN ? "bat" : "sh") );
+        if (script.exists()) return script.getAbsolutePath();
+        throw new MojoFailureException("Cannot find a default script to launch.");
+    }
+
+    protected boolean canConnect() {
+        try {
+            URL url = getWebUrl();
+            HttpURLConnection con;
+            con = (HttpURLConnection) url.openConnection();
+            return (con.getResponseCode() > 0);
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    public void killControllers() {
+        getLog().info("Checking environment for stray processes.");
+        List<JavaProcess> jvms = procMon.getProcesses(MAIN_CLASS, CTRL_PROP);
+        for (JavaProcess j : jvms) {
+            getLog().info("Killing running process: " + j);
+            ProcessMonitor.kill(j.getPid());
+        }
+        // cleanup pid files
+        getLog().info("Checking left over pid file: " + pidFile);
+        if (pidFile != null && pidFile.exists()) {
+            getLog().info("Cleaning up pid file : " + pidFile);
+            pidFile.delete();
+        }
+    }
+
+    public boolean isControllerRunning() {
+        return !procMon.getProcesses(MAIN_CLASS, CTRL_PROP).isEmpty();
+    }
+
+}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StartControllerMojo.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StartControllerMojo.java
new file mode 100644 (file)
index 0000000..0a3bee4
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.maven.plugin;
+
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+
+/**
+ * Starts the controller
+ */
+@Mojo( name = "run", defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST )
+public class StartControllerMojo extends AbstractControllerMojo {
+    public static final String REDIRECT_LOG = "controller.out";
+
+    /**
+     * The timeout value for starting the controller. Defaults to 60 secs
+     */
+    @Parameter(defaultValue = "60")
+    public int timeoutSecs = 60;
+
+    /**
+     * The startArgs for starting the controller
+     */
+    @Parameter(required = false)
+    protected List<String> startArgs = new ArrayList<String>();
+
+    /**
+     * The time to wait after successfully connecting to the controller and
+     * before returning from execution.
+     */
+    @Parameter(required = false)
+    protected int warmupTimeSecs = 10;
+
+
+    @Override
+    public void start() throws MojoExecutionException, MojoFailureException {
+        killControllers();
+        // if we can still connect to a controller, bail out
+        if (canConnect()) {
+            getLog().error("A controller is already running. Shutdown and retry.");
+            throw new MojoFailureException("Controller is already running.");
+        }
+        startArgs.add("-D" + CTRL_PROP);
+        Process process = invokeScript(startArgs, REDIRECT_LOG);
+        getLog().info("Controller starting... (waiting for open ports)");
+        try {
+            waitForListening(process);
+            getLog().info("Controller port open. Waiting for warmup: "
+                    + warmupTimeSecs);
+            Thread.sleep(warmupTimeSecs*1000);
+        } catch (Exception e) {
+            throw new MojoExecutionException(e.getMessage());
+        }
+        getLog().info("Controller started successfully.");
+    }
+
+    protected boolean waitForListening(Process process)
+            throws MalformedURLException, InterruptedException, MojoExecutionException
+    {
+        long timeElapsedMillis = 0L;
+        long sleepTimeMillis = 2000L; // 2 secs
+        long timeoutMillis = timeoutSecs * 1000;
+
+        while (timeElapsedMillis < timeoutMillis) {
+            long timeRemaining = timeoutMillis - timeElapsedMillis;
+            sleepTimeMillis *= 2;
+            long toSleep = (sleepTimeMillis > timeRemaining)
+                    ? timeRemaining : sleepTimeMillis;
+            Thread.sleep(toSleep);
+            timeElapsedMillis += toSleep;
+            if (canConnect()) {
+                return true;
+            }
+            if (!isControllerRunning()) {
+                throw new MojoExecutionException("Process seems to have exited prematurely.");
+            }
+        }
+        return false;
+    }
+}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StopControllerMojo.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/StopControllerMojo.java
new file mode 100644 (file)
index 0000000..579778d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.maven.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+
+/**
+ * Stop controller
+ */
+@Mojo( name = "stop", defaultPhase = LifecyclePhase.POST_INTEGRATION_TEST )
+public class StopControllerMojo extends AbstractControllerMojo {
+    private static final boolean SKIP_STOP = Boolean.getBoolean("skipControllerStop");
+
+    @Override
+    public void start() throws MojoExecutionException, MojoFailureException {
+        if (SKIP_STOP) {
+            getLog().info("Controller STOP is skipped per configuration " +
+                    "(-DskipControllerStop=true).");
+            return;
+        }
+        if (canConnect()) {
+            List<String> args = new ArrayList<String>();
+            args.add("-stop");
+            Process proc = invokeScript(args, null);
+            try {
+                int status = proc.waitFor();
+                if (status == 0) {
+                    getLog().info("Controller stopped.");
+                } else {
+                    getLog().error("Error stopping controller. See stdout log for details.");
+                }
+            } catch (InterruptedException ie) {
+                throw new MojoExecutionException("Error stopping controller : " + ie.getMessage());
+            }
+        } else {
+            getLog().info("Controller not running.");
+        }
+        // cleanup for any hung processes
+        killControllers();
+    }
+
+}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JavaProcess.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JavaProcess.java
new file mode 100644 (file)
index 0000000..95da34f
--- /dev/null
@@ -0,0 +1,57 @@
+
+/*
+ * 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.maven.plugin.util;
+
+import java.util.Properties;
+
+public class JavaProcess {
+    private final int pid;
+    private final String mainClass;
+    private final Properties systemProperties = new Properties();
+
+    public JavaProcess(int id, String cls) {
+        this.pid = id;
+        this.mainClass = cls;
+    }
+
+    public void setSystemProperties(String line) {
+        if (line == null || line.length() == 0) return;
+        String[] tokens = line.split("\\s");
+        for (String t : tokens) setSystemProperty(t);
+    }
+
+    public void setSystemProperty(String line) {
+        if (line.startsWith("-D")) {
+            int x = line.indexOf('=');
+            if (x > -1) {
+                systemProperties.put(line.substring(2, x), line.substring(x+1));
+            } else {
+                systemProperties.put(line.substring(2), "");
+            }
+        }
+    }
+
+    public int getPid() {
+        return pid;
+    }
+
+    public String getMainClass() {
+        return mainClass;
+    }
+
+    public Properties getSystemProperties() {
+        return systemProperties;
+    }
+
+    @Override
+    public String toString() {
+        return "pid:" + pid + " class:" + mainClass +
+                " system-properties:" + systemProperties.toString();
+    }
+}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JpsProcessMonitor.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/JpsProcessMonitor.java
new file mode 100644 (file)
index 0000000..8474266
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.maven.plugin.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Uses JPS tool to monitor java local processes
+ */
+public class JpsProcessMonitor extends ProcessMonitor {
+    private final String jpsTool;
+
+    public JpsProcessMonitor() {
+        String jh = System.getProperty("java.home");
+        File jps = new File(jh + SEP + "bin" + SEP + "jps");
+        if (!jps.exists()) {
+            // try one dir above
+            jps = new File(jh + SEP + ".." + SEP + "bin" + SEP + "jps");
+            if (!jps.exists()) {
+                throw new IllegalStateException("jps tool cannot be located.");
+            }
+        }
+        jpsTool = jps.getAbsolutePath();
+    }
+
+    @Override
+    public List<JavaProcess> getProcesses() {
+        if (jpsTool == null) return super.getProcesses();
+        List<JavaProcess> jvms = new ArrayList<JavaProcess>();
+        try {
+            ProcessBuilder pb = new ProcessBuilder();
+            pb.command(new String[] { jpsTool, "-mlvV"} );
+            pb.redirectErrorStream(true);
+            Process process = pb.start();
+            BufferedReader br = new BufferedReader(
+                    new InputStreamReader(process.getInputStream()));
+            String line = null;
+            while ( (line = br.readLine()) != null) {
+                JavaProcess j = parseLine(line);
+                if (j != null) jvms.add(j);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return jvms;
+    }
+
+    public static JavaProcess parseLine(String line) {
+        String[] tokens = line.split("\\s");
+        if (tokens.length < 2) {
+            System.out.println("Unable to parse line: " + line);
+            return null;
+        }
+        int idx = 0;
+        int pid = Integer.parseInt(tokens[idx++]);
+        String mainClass = "";
+        if (!tokens[idx].startsWith("-")) {
+            mainClass = tokens[idx++];
+        }
+        JavaProcess proc = new JavaProcess(pid, mainClass);
+        for (int i=idx; i<tokens.length; i++) {
+            if (tokens[i].startsWith("-D")) {
+                proc.setSystemProperty(tokens[i]);
+            }
+        }
+        return proc;
+    }
+
+}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/ProcessMonitor.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/ProcessMonitor.java
new file mode 100644 (file)
index 0000000..5c3c69f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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.maven.plugin.util;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ProcessMonitor {
+    public static final String SEP = File.pathSeparator;
+    public static final boolean WIN =
+            System.getProperty("os.name").toLowerCase().indexOf("windows") > -1;
+
+
+
+    public void log(String msg) {
+        System.out.println("" + msg);
+    }
+
+    public List<JavaProcess> getProcesses() {
+        return Collections.emptyList();
+    }
+
+    public List<JavaProcess> getProcesses(String mainClass, String systemPropertyKey) {
+        List<JavaProcess> result = new ArrayList<JavaProcess>();
+         for (JavaProcess info : getProcesses()) {
+            if (info.getMainClass().equals(mainClass)) {
+                if (info.getSystemProperties().containsKey(systemPropertyKey)) {
+                    result.add(info);
+                }
+            }
+        }
+        return result;
+    }
+
+    public int kill(String mainClass) {
+        for (JavaProcess info : getProcesses()) {
+            if (info.getMainClass().equals(mainClass)) {
+                log("Killing process matching class: " + mainClass);
+                return kill(info.getPid());
+            }
+        }
+        return -1;
+    }
+
+    public static int kill(int pid)  {
+        String cmd = WIN ? "TASKKILL /F /PID " + pid : "kill -SIGTERM " + pid;
+        try {
+            Process p = Runtime.getRuntime().exec(cmd);
+            p.waitFor();
+            return p.exitValue();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return -1;
+        }
+    }
+
+    public static ProcessMonitor load() {
+        // load the providers dynamically to allow error handling
+        ProcessMonitor pm = load("org.opendaylight.controller.maven.plugin.util.VMProcessMonitor");
+        if (pm == null) {
+            pm = load("org.opendaylight.controller.maven.plugin.util.JpsProcessMonitor");
+        }
+        return (pm == null ? new ProcessMonitor() : pm);
+    }
+
+    private static ProcessMonitor load(String clz) {
+        try {
+            Class c = Class.forName(clz);
+            return (ProcessMonitor) c.newInstance();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    // simple driver for basic manual testing
+    public static void main(String[] args) throws Exception {
+        ProcessMonitor pm = ProcessMonitor.load();
+        System.out.println("==== " + pm);
+        for (JavaProcess info : pm.getProcesses()) {
+            System.out.println(info.toString());
+        }
+        pm.kill("Foo");
+        System.out.println("==== controller processses ");
+        for (JavaProcess info : pm.getProcesses(
+                "org.eclipse.equinox.launcher.Main", "opendaylight.controller"))
+        {
+            System.out.println(info.toString());
+            pm.kill(info.getPid());
+        }
+    }
+
+}
diff --git a/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/VMProcessMonitor.java b/opendaylight/commons/controller-maven-plugin/src/main/java/org/opendaylight/controller/maven/plugin/util/VMProcessMonitor.java
new file mode 100644 (file)
index 0000000..fdf232a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.maven.plugin.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import sun.jvmstat.monitor.HostIdentifier;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredVm;
+import sun.jvmstat.monitor.MonitoredVmUtil;
+import sun.jvmstat.monitor.VmIdentifier;
+
+public class VMProcessMonitor extends ProcessMonitor {
+
+    @Override
+    public List<JavaProcess> getProcesses() {
+        Set<Integer> activeVmPids = null;
+        List<JavaProcess> result = new ArrayList<JavaProcess>();
+        MonitoredHost monitoredHost = null;
+        MonitoredVm mvm = null;
+        try {
+            monitoredHost = MonitoredHost.getMonitoredHost(
+                    new HostIdentifier((String) null));
+            activeVmPids = monitoredHost.activeVms();
+        } catch (Exception e) {
+            throw new IllegalStateException("Error accessing VM", e);
+        }
+        for (Integer vmPid : activeVmPids) {
+            try {
+                mvm = monitoredHost.getMonitoredVm(
+                        new VmIdentifier(vmPid.toString()));
+                JavaProcess proc = new JavaProcess(vmPid,
+                        MonitoredVmUtil.mainClass(mvm, true));
+                proc.setSystemProperties(MonitoredVmUtil.jvmArgs(mvm));
+                proc.setSystemProperties(MonitoredVmUtil.jvmFlags(mvm));
+                result.add(proc);
+            } catch(Exception e2) {
+                log("Error connecting to pid: " + vmPid + " reason:"
+                    + e2.getMessage());
+                e2.printStackTrace();
+            } finally {
+                if (mvm != null) {
+                    mvm.detach();
+                }
+            }
+        }
+        return result;
+    }
+
+
+}
index dd73815b34475757d6950662bcbcfc0dd165a51f..07c89166f9c397b9289ae4b7658b0354b3eb6a7a 100644 (file)
@@ -70,6 +70,8 @@
     <jacoco.version>0.5.3.201107060350</jacoco.version>
     <enforcer.version>1.3.1</enforcer.version>
     <bundle.plugin.version>2.3.7</bundle.plugin.version>
+    <install.plugin.version>2.5</install.plugin.version>
+    <enforcer.plugin.version>1.3.1</enforcer.plugin.version>
     <junit.version>4.8.1</junit.version>
     <bgpcep.version>0.3.0-SNAPSHOT</bgpcep.version>
     <yangtools.version>0.5.9-SNAPSHOT</yangtools.version>
index 5f23c90bbed10ef8a6068d30317d8448132b59b0..56b96e97bba0ccaad7e45cdd9b2f96dace898c6c 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 7e8ee64daa089fec089d8d0d57b31cba364f25c9..c257e55dc088b7b7d80bb99fea333e5aacc33c6e 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 7a3c4bf82d4dec0dbc5e3b43462fa57e29f17ddb..897547135341a5d60216e6e6b5cabfca5ecc7bce 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 a81d992d81ae1cbae4d711e9a18be194524eba71..e66de46520a11741e42c4cf72049ff6d18d2b0df 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 8111690c72bb9b65df66b1afe83f7fc79cc2e3d3..cc1d89761c2ef8784b6f79019101fa76a21361c1 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 7b8f7c164efd716f6c1f38e6029636a9bc9e2522..c86b38149377733fdc59d3281f97a49d31dcd3d6 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 1b695a9bda2fe42a2fcdd042636e9bff4b0a511d..18326d91f21b8df58afd905746b2efc606ebb1ce 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 3e53a7a217e1855dedb596a2b5f1dedcd707ca85..36485b1abfe032d27f57169310cea285233b959b 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 4dc877c62b339bebad0a55848c6debc25b96300a..82bae44a01b60148b9105e4e8ef98cc1530daf9f 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 065a0f843f501cdb7e2a4230c9cc0b72caf31f3c..760fe50e28f533021684f1d1a0bb25685272fac8 100644 (file)
@@ -48,6 +48,7 @@ final class DependencyResolverImpl implements DependencyResolver,
     /**
      * {@inheritDoc}
      */
+    //TODO: check for cycles
     @Override
     public void validateDependency(
             Class<? extends AbstractServiceInterface> expectedServiceInterface,
@@ -101,6 +102,7 @@ final class DependencyResolverImpl implements DependencyResolver,
     /**
      * {@inheritDoc}
      */
+    //TODO: check for cycles
     @Override
     public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentON,
             JmxAttribute jmxAttribute) {
index 523cbc5b013c48724a68a5c5518003afdb435b61..b371c3f1709c3160bc2c2a372f0d7647dec24253 100644 (file)
@@ -65,7 +65,7 @@ public class TransactionJMXRegistrator implements Closeable {
     }
 
     @Override
-    public void close() {
+    public void close() { // closes also all child TransactionModuleJMXRegistrator instances
         childJMXRegistrator.close();
     }
 }
index 76cb64cf9349ae62cc99d7f66eb12e7f66a0ed74..033f7222fcc7fd64103e25336a3b81f669d14adc 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;
+    }
 }
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigWithJolokiaTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigWithJolokiaTest.java
deleted file mode 100644 (file)
index de26220..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.junit.After;
-import org.junit.Before;
-import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
-import org.opendaylight.controller.config.util.JolokiaHelper;
-import org.opendaylight.controller.config.util.jolokia.ConfigRegistryJolokiaClient;
-
-public class AbstractConfigWithJolokiaTest extends AbstractConfigTest {
-    protected String jolokiaURL;
-    protected ConfigRegistryJolokiaClient configRegistryJolokiaClient;
-
-    @Before
-    public void initJolokia() {
-        jolokiaURL = JolokiaHelper.startTestingJolokia();
-    }
-
-    // this method should be called in @Before
-    @Override
-    protected void initConfigTransactionManagerImpl(
-            ModuleFactoriesResolver resolver) {
-        super.initConfigTransactionManagerImpl(resolver);
-        configRegistryJolokiaClient = new ConfigRegistryJolokiaClient(
-                jolokiaURL);
-    }
-
-    @After
-    public void cleanUpJolokia() {
-        JolokiaHelper.stopJolokia();
-    }
-}
index d23b5ca1282739935e73a27278fab6a7d2fcb904..672f15091430f26532a20cf3636cbad0e6eee477 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 22a959060cfaca6d598e8e84a41225352bd00eb1..43c75ef1e7b2b1797415fa196b00f6370e3eec0d 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 eaaee5eb5be5aa5d54d1525b11e101e6fa49ff92..bbb3784b33b02e49be8929d39e983e2c4cb7d33a 100644 (file)
@@ -7,23 +7,19 @@
  */
 package org.opendaylight.controller.config.manager.impl;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-
-import javax.management.InstanceAlreadyExistsException;
-
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.api.jmx.constants.ConfigRegistryConstants;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import org.opendaylight.controller.config.util.jolokia.ConfigTransactionJolokiaClient;
+
+import javax.management.InstanceAlreadyExistsException;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
 
 public class ConfigTransactionManagerImplTest extends
-        AbstractConfigWithJolokiaTest {
+        AbstractConfigTest {
 
     @Before
     public void setUp() {
@@ -55,23 +51,4 @@ public class ConfigTransactionManagerImplTest extends
         transaction.commit();
     }
 
-    @Test
-    public void testRemoteCallsUsingJolokia() throws Exception {
-
-        ConfigTransactionJolokiaClient transactionClient = configRegistryJolokiaClient
-                .createTransaction();
-
-        assertEquals("ConfigTransaction-0-1",
-                ObjectNameUtil.getTransactionName(transactionClient
-                        .getTransactionON()));
-
-        assertEquals(
-                ConfigRegistryConstants.ON_DOMAIN
-                        + ":TransactionName=ConfigTransaction-0-1,type=ConfigTransaction",
-                transactionClient.getTransactionON().getCanonicalName());
-
-        // commit
-        transactionClient.commit();
-
-    }
 }
index cf6ed18c6cd96b4483ac8f1f9064a84ae2ea1db2..75b0414711095d70b3e98f7964c84ff422a3ec75 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 9a5452aa6caa237cc702d1b81b8b388d4520cfd0..22ea528030931b5350cd79c0facc30d1c4ed73a5 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 4fd2f5f1b5a08676458d211b37cfb1d6f2d2ad7f..9674a110ce18fd742f8534915fa8713a2ce4b550 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 3adf11484e6506299468c17e42f33976567f988d..50a58792e14b700b0bd43ddcccbb9517c9c3a0ab 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 7deb1efb55c5ae68c2016a7c1816eba27b8b2de4..3d9d5245ef2886be3eaa937312c247541e50557e 100644 (file)
@@ -7,16 +7,16 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
-import org.opendaylight.controller.config.manager.impl.AbstractConfigWithJolokiaTest;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPConfigMXBean;
 import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolConfigMXBean;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 
-abstract class AbstractParallelAPSPTest extends AbstractConfigWithJolokiaTest {
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
     protected final String fixed1 = "fixed1";
     protected final String apsp1 = "apsp-parallel";
 
index 5b1a6f6e8184f69805ec5245e2d4b99089467e5d..f9a11301e1aaf09b98d8af43bd965f1f8902e153 100644 (file)
@@ -7,17 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.parallelapsp.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.junit.internal.matchers.StringContains.containsString;
-
-import java.util.Map;
-
-import javax.management.ObjectName;
-
-import org.json.simple.JSONObject;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -32,7 +21,15 @@ import org.opendaylight.controller.config.manager.testingservices.threadpool.Tes
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolConfigMXBean;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import org.opendaylight.controller.config.util.jolokia.ConfigTransactionJolokiaClient;
+
+import javax.management.ObjectName;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.internal.matchers.StringContains.containsString;
 
 public class DependentWiringTest extends AbstractParallelAPSPTest {
     private final String fixed1 = "fixed1";
@@ -135,44 +132,4 @@ public class DependentWiringTest extends AbstractParallelAPSPTest {
                 parallelAPSPRuntimeProxy.getMaxNumberOfThreads());
 
     }
-
-    @Test
-    public void testUsingJolokia() throws Exception {
-
-        ConfigTransactionJolokiaClient transactionClient = configRegistryJolokiaClient
-                .createTransaction();
-        // fixed1
-        ObjectName fixed1ON = transactionClient.createModule(
-                getThreadPoolImplementationName(), fixed1);
-        transactionClient.setAttribute(fixed1ON, "ThreadCount",
-                TestingParallelAPSPImpl.MINIMAL_NUMBER_OF_THREADS);
-
-        // apsp-parallel with syntetic attrib
-        String threadPoolString = "ThreadPool";
-        ObjectName apsp1ON = transactionClient.createModule(
-                TestingParallelAPSPModuleFactory.NAME, apsp1);
-        transactionClient.setAttribute(apsp1ON, threadPoolString, fixed1ON);
-        // check
-        assertEquals(ObjectNameUtil.withoutTransactionName(fixed1ON),
-                transactionClient.getAttributeON(apsp1ON, threadPoolString));
-        transactionClient.setAttribute(apsp1ON, "SomeParam", "ahoj");
-
-        // commit
-        transactionClient.commit();
-        // check thread pool
-        assertEquals(1, TestingFixedThreadPool.allExecutors.size());
-        // check platform MBeanServer
-        ObjectName apspReadOnlyON = ObjectNameUtil
-                .withoutTransactionName(apsp1ON);
-        JSONObject threadPoolONJson = (JSONObject) configRegistryJolokiaClient
-                .getAttribute(apspReadOnlyON, threadPoolString);
-        ObjectName fixed1ReadOnlyON = ObjectNameUtil
-                .withoutTransactionName(fixed1ON);
-        assertEquals(fixed1ReadOnlyON, ObjectNameUtil.createON(threadPoolONJson
-                .get("objectName").toString()));
-        assertEquals(fixed1ReadOnlyON,
-                configRegistryJolokiaClient.getAttributeON(apspReadOnlyON,
-                        threadPoolString));
-
-    }
 }
index 2e1047849e6773c02e3b6d4fe6f7b1f94ba9198a..e5306a4fa60272e23adac53af8f83f5454876b86 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 ab1b6bd2184d4f9d4114ea067e0dbf4f9ce090cd..5c30d1e977fafbed51ba19c87e4027ec67d87bd1 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 e4e388c610e6ac5459ea4581a4be9a061501986d..5ddc1892e3b4139320eaee85c865b5437ae09895 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 fd5ab1780d7afe7feae4f4e4d4d68ee595f381eb..91a4cff415ac3200366deee7c4324a9755423a89 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 cf05e445306b30eb16ac8740bb30ec83a7452649..b749ea751151e2280d06938e4708c61ce62ddc23 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 c2f2558a5d202d5c0279eaef157c913bc2ff7889..13bb84040a10d7d7e4bc4aabfde2401408f11c5b 100644 (file)
@@ -7,28 +7,6 @@
  */
 package org.opendaylight.controller.config.manager.testingservices.threadpool.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.junit.matchers.JUnitMatchers.containsString;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ThreadPoolExecutor;
-
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanException;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import javax.management.RuntimeMBeanException;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -37,14 +15,32 @@ import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.ValidationException.ExceptionMessageWithStackTrace;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.AbstractConfigWithJolokiaTest;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolConfigMXBean;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import org.opendaylight.controller.config.util.jolokia.ConfigTransactionJolokiaClient;
+
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeMBeanException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 /**
  * Tests basic functionality of configuration registry:
@@ -58,7 +54,7 @@ import org.opendaylight.controller.config.util.jolokia.ConfigTransactionJolokiaC
  * Only one bean is being configured - {@link TestingThreadPoolIfc} which has no
  * dependencies.
  */
-public class SimpleConfigurationTest extends AbstractConfigWithJolokiaTest {
+public class SimpleConfigurationTest extends AbstractConfigTest {
     private final int numberOfThreads = 5;
     private final int numberOfThreads2 = 10;
     private static final String fixed1 = "fixed1";
@@ -134,12 +130,6 @@ public class SimpleConfigurationTest extends AbstractConfigWithJolokiaTest {
         testValidation(transaction);
     }
 
-    @Test
-    public void testValidationUsingJolokiaClient() throws Exception {
-        ConfigTransactionClient transaction = configRegistryJolokiaClient
-                .createTransaction();
-        testValidation(transaction);
-    }
 
     private void testValidation(ConfigTransactionClient transaction)
             throws InstanceAlreadyExistsException, ReflectionException,
@@ -393,68 +383,5 @@ public class SimpleConfigurationTest extends AbstractConfigWithJolokiaTest {
         }
     }
 
-    @Test
-    public void testOptimisticLock_ConfigTransactionJolokiaClient()
-            throws Exception {
-        ConfigTransactionJolokiaClient transaction1 = configRegistryJolokiaClient
-                .createTransaction();
-        ConfigTransactionJolokiaClient transaction2 = configRegistryJolokiaClient
-                .createTransaction();
-        transaction2.assertVersion(0, 2);
-        transaction2.commit();
-        try {
-            transaction1.commit();
-            fail();
-        } catch (ConflictingVersionException e) {
-            assertEquals(
-                    "Optimistic lock failed. Expected parent version 2, was 0",
-                    e.getMessage());
-        }
-    }
-
-    @Test
-    public void testOptimisticLock_ConfigRegistryJolokiaClient()
-            throws Exception {
-        ConfigTransactionJolokiaClient transaction1 = configRegistryJolokiaClient
-                .createTransaction();
-        ConfigTransactionJolokiaClient transaction2 = configRegistryJolokiaClient
-                .createTransaction();
-        transaction2.assertVersion(0, 2);
-        transaction2.commit();
-        try {
-            configRegistryJolokiaClient.commitConfig(transaction1
-                    .getObjectName());
-            fail();
-        } catch (ConflictingVersionException e) {
-            assertEquals(
-                    "Optimistic lock failed. Expected parent version 2, was 0",
-                    e.getMessage());
-        }
-    }
-
-    @Test
-    public void testUsingJolokia() throws Exception {
-        ConfigTransactionJolokiaClient transactionClient = configRegistryJolokiaClient
-                .createTransaction();
-
-        ObjectName name = transactionClient.createModule(
-                TestingFixedThreadPoolModuleFactory.NAME, fixed1);
-
-        try {
-            transactionClient.validateConfig();
-            fail();
-        } catch (ValidationException e) {
-            assertThat(
-                    e.getMessage(),
-                    containsString("Parameter 'threadCount' must be greater than 0"));
-        }
-
-        transactionClient.setAttribute(name, "ThreadCount", numberOfThreads);
-        // commit
-        CommitStatus commitStatus = transactionClient.commit();
-        CommitStatus expected = new CommitStatus(Arrays.asList(ObjectNameUtil
-                .withoutTransactionName(name)), emptyONs, emptyONs);
-        assertEquals(expected, commitStatus);
-    }
 
 }
index 206184ccce0b6f2f3209fa0a2c4a728f986eefa0..23603ae626554714da53e1f14897f285e2418b14 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>config-api</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.jolokia</groupId>
-            <artifactId>jolokia-client-java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jolokia</groupId>
-            <artifactId>jolokia-jvm</artifactId>
-            <classifier>agent</classifier>
-        </dependency>
-
         <!-- test dependencies -->
         <dependency>
             <groupId>com.google.guava</groupId>
index 3a1efaeaaf1992163e794f950f1f48b743c64204..4ecc7c3a5c572cfc50fb2a90ef5b08bf35a7d537 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 548c0e9ea4f6eedc7c317cabc7cbc820cda03f62..bd6f6fa884fe0521bff93d8e0fc665e78c529dd7 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 {
diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigRegistryJolokiaClient.java
deleted file mode 100644 (file)
index f29f0e0..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.util.jolokia;
-
-import java.util.List;
-import java.util.Set;
-
-import javax.management.ObjectName;
-
-import org.jolokia.client.request.J4pExecRequest;
-import org.jolokia.client.request.J4pReadRequest;
-import org.jolokia.client.request.J4pResponse;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.jmx.CommitStatus;
-import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.util.ConfigRegistryClient;
-
-public class ConfigRegistryJolokiaClient extends ListableJolokiaClient
-        implements ConfigRegistryClient {
-
-    public ConfigRegistryJolokiaClient(String url) {
-        super(url, ConfigRegistryMXBean.OBJECT_NAME);
-    }
-
-    @Override
-    public ConfigTransactionJolokiaClient createTransaction() {
-        // create transaction
-        J4pExecRequest execReq = new J4pExecRequest(objectName, "beginConfig");
-        J4pResponse<J4pExecRequest> resp = execute(execReq);
-        ObjectName transactionControllerON = extractObjectName(resp);
-        return getConfigTransactionClient(transactionControllerON);
-    }
-
-    @Override
-    public ConfigTransactionJolokiaClient getConfigTransactionClient(
-            String transactionName) {
-        ObjectName objectName = ObjectNameUtil
-                .createTransactionControllerON(transactionName);
-        return getConfigTransactionClient(objectName);
-    }
-
-    @Override
-    public ConfigTransactionJolokiaClient getConfigTransactionClient(
-            ObjectName objectName) {
-        return new ConfigTransactionJolokiaClient(url, objectName, this);
-    }
-
-    @Override
-    public CommitStatus commitConfig(ObjectName transactionControllerON)
-            throws ConflictingVersionException, ValidationException {
-        J4pExecRequest execReq = new J4pExecRequest(objectName, "commitConfig",
-                transactionControllerON);
-        JSONObject jsonObject;
-        jsonObject = execute(execReq).getValue();
-        JSONArray newInstancesArray = (JSONArray) jsonObject
-                .get("newInstances");
-        List<ObjectName> newInstances = jsonArrayToObjectNames(newInstancesArray);
-        JSONArray reusedInstancesArray = (JSONArray) jsonObject
-                .get("reusedInstances");
-        List<ObjectName> reusedInstances = jsonArrayToObjectNames(reusedInstancesArray);
-        JSONArray recreatedInstancesArray = (JSONArray) jsonObject
-                .get("recreatedInstances");
-        List<ObjectName> recreatedInstances = jsonArrayToObjectNames(recreatedInstancesArray);
-        return new CommitStatus(newInstances, reusedInstances,
-                recreatedInstances);
-    }
-
-    public Object getAttribute(ObjectName configBeanTransactionON, String key) {
-        J4pReadRequest req = new J4pReadRequest(configBeanTransactionON, key);
-        return execute(req).getValue();
-    }
-
-    public ObjectName getAttributeON(ObjectName configBeanTransactionON,
-            String key) {
-        JSONObject jsonAttrib = (JSONObject) getAttribute(
-                configBeanTransactionON, key);
-        return extractObjectName(jsonAttrib);
-    }
-
-    // proxy around ConfigTransactionManagerMXBean
-
-    @Override
-    public ObjectName beginConfig() {
-        ConfigTransactionJolokiaClient result = createTransaction();
-        return result.getTransactionON();
-    }
-
-    @Override
-    public List<ObjectName> getOpenConfigs() {
-        J4pReadRequest req = new J4pReadRequest(objectName, "OpenConfigs");
-        JSONArray jsonArray = execute(req).getValue();
-        return jsonArrayToObjectNames(jsonArray);
-    }
-
-    @Override
-    public long getVersion() {
-        J4pReadRequest req = new J4pReadRequest(objectName, "Version");
-        return (Long) execute(req).getValue();
-    }
-
-    @Override
-    public boolean isHealthy() {
-        J4pReadRequest req = new J4pReadRequest(objectName, "Healthy");
-        return (Boolean) execute(req).getValue();
-    }
-
-    @Override
-    public Set<ObjectName> lookupRuntimeBeans() {
-        return lookupSomething("lookupRuntimeBeans()", new Object[0]);
-    }
-
-    @Override
-    public Set<ObjectName> lookupRuntimeBeans(String moduleName,
-            String instanceName) {
-        return lookupSomething(
-                "lookupRuntimeBeans(java.lang.String,java.lang.String)",
-                new Object[] { moduleName, instanceName });
-    }
-
-    @Override
-    public Object invokeMethod(ObjectName on, String name, Object[] params,
-            String[] signature) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Object getAttributeCurrentValue(ObjectName on, String attributeName) {
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ConfigTransactionJolokiaClient.java
deleted file mode 100644 (file)
index f4824cd..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.util.jolokia;
-
-import java.util.Map;
-
-import javax.management.Attribute;
-import javax.management.AttributeNotFoundException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-
-import org.jolokia.client.request.J4pExecRequest;
-import org.jolokia.client.request.J4pReadRequest;
-import org.jolokia.client.request.J4pWriteRequest;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.jmx.CommitStatus;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.util.AttributeEntry;
-import org.opendaylight.controller.config.util.ConfigTransactionClient;
-
-public class ConfigTransactionJolokiaClient extends ListableJolokiaClient
-        implements ConfigTransactionClient {
-
-    private final ConfigRegistryJolokiaClient configRegistryJolokiaClient;
-
-    public ConfigTransactionJolokiaClient(String url,
-            ObjectName transactionControllerON,
-            ConfigRegistryJolokiaClient configRegistryJolokiaClient) {
-        super(url, transactionControllerON);
-        this.configRegistryJolokiaClient = configRegistryJolokiaClient;
-    }
-
-    public ObjectName getTransactionON() {
-        return objectName;
-    }
-
-    @Override
-    public CommitStatus commit() throws ConflictingVersionException,
-            ValidationException {
-        return configRegistryJolokiaClient.commitConfig(objectName);
-    }
-
-    @Override
-    public ObjectName createModule(String moduleName, String instanceName)
-            throws InstanceAlreadyExistsException {
-        J4pExecRequest execReq = new J4pExecRequest(objectName, "createModule",
-                moduleName, instanceName);
-        try {
-            return extractObjectName(execute(execReq));
-        } catch (RuntimeException e) {
-            if (e.getMessage() != null
-                    && e.getMessage().startsWith(
-                            InstanceAlreadyExistsException.class.getName()))
-                throw new InstanceAlreadyExistsException();
-            throw e;
-        }
-    }
-
-    @Override
-    public void destroyModule(ObjectName configBeanON) {
-        J4pExecRequest execReq = new J4pExecRequest(objectName,
-                "destroyModule(javax.management.ObjectName)", configBeanON);
-        execute(execReq);
-    }
-
-    @Override
-    public void destroyConfigBean(String moduleName, String instanceName)
-            throws InstanceNotFoundException {
-        destroyModule(ObjectNameUtil.createTransactionModuleON(
-                getTransactionName(), moduleName, instanceName));
-    }
-
-    @Override
-    public void abortConfig() {
-        J4pExecRequest execReq = new J4pExecRequest(objectName, "abortConfig");
-        execute(execReq);
-    }
-
-    @Override
-    public void validateConfig() throws ValidationException {
-        J4pExecRequest execReq = new J4pExecRequest(objectName,
-                "validateConfig");
-        execute(execReq);
-    }
-
-    @Override
-    public long getParentVersion() {
-        J4pReadRequest req = new J4pReadRequest(objectName, "ParentVersion");
-        return (Long) execute(req).getValue();
-    }
-
-    @Override
-    public long getVersion() {
-        J4pReadRequest req = new J4pReadRequest(objectName, "Version");
-        return (Long) execute(req).getValue();
-    }
-
-    public void setAttribute(ObjectName configBeanTransactionON, String key,
-            Object value) {
-        J4pWriteRequest req = new J4pWriteRequest(configBeanTransactionON, key,
-                value);
-        try {
-            execute(req);
-        } catch (RuntimeException e) {
-            if (e.getMessage() != null
-                    && e.getMessage().startsWith(
-                            AttributeNotFoundException.class.getName())) {
-                // try to fix wrong case
-                Map<String, AttributeEntry> allAttributes = getAttributes(configBeanTransactionON);
-                for (AttributeEntry attrib : allAttributes.values()) {
-                    if (attrib.getKey().equalsIgnoreCase(key)) {
-                        req = new J4pWriteRequest(configBeanTransactionON,
-                                attrib.getKey(), value);
-                        execute(req);
-                        return;
-                    }
-                }
-            }
-            throw e;
-        }
-    }
-
-    public Object getAttribute(ObjectName objectName, String key) {
-        return configRegistryJolokiaClient.getAttribute(objectName, key);
-    }
-
-    public ObjectName getAttributeON(ObjectName objectName, String key) {
-        return configRegistryJolokiaClient.getAttributeON(objectName, key);
-    }
-
-    @Override
-    public String getTransactionName() {
-        return ObjectNameUtil.getTransactionName(objectName);
-    }
-
-    @Override
-    public void validateBean(ObjectName rwON) throws ValidationException {
-        J4pExecRequest req = new J4pExecRequest(rwON, "validate", new Object[0]);
-        execute(req);
-    }
-
-    @Override
-    public void assertVersion(int expectedParentVersion,
-            int expectedCurrentVersion) {
-        if (expectedParentVersion != getParentVersion()) {
-            throw new IllegalStateException();
-        }
-        if (expectedCurrentVersion != getVersion()) {
-            throw new IllegalStateException();
-        }
-    }
-
-    @Override
-    public void setAttribute(ObjectName on, String jmxName, Attribute attribute) {
-        throw new UnsupportedOperationException();
-    }
-
-}
diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClient.java
deleted file mode 100644 (file)
index 6277f6a..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * 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.util.jolokia;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-
-import org.jolokia.client.J4pClient;
-import org.jolokia.client.exception.J4pException;
-import org.jolokia.client.exception.J4pRemoteException;
-import org.jolokia.client.request.J4pExecRequest;
-import org.jolokia.client.request.J4pListRequest;
-import org.jolokia.client.request.J4pQueryParameter;
-import org.jolokia.client.request.J4pReadRequest;
-import org.jolokia.client.request.J4pRequest;
-import org.jolokia.client.request.J4pResponse;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.opendaylight.controller.config.api.ConflictingVersionException;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.ValidationException.ExceptionMessageWithStackTrace;
-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;
-    protected final ObjectName objectName;
-
-    public ListableJolokiaClient(String url, ObjectName objectName) {
-        if (url == null) {
-            throw new NullPointerException("Parameter 'url' is null");
-        }
-        if (!url.endsWith("/")) {
-            throw new IllegalArgumentException(
-                    "Parameter 'url' must end with '/'");
-        }
-
-        this.url = url;
-        this.j4pClient = new J4pClient(url);
-        this.objectName = objectName;
-    }
-
-    public ObjectName getObjectName() {
-        return objectName;
-    }
-
-    protected <R extends J4pResponse<T>, T extends J4pRequest> R execute(
-            T pRequest) {
-        try {
-            Map<J4pQueryParameter, String> pProcessingOptions = new HashMap<J4pQueryParameter, String>();
-            pProcessingOptions
-                    .put(J4pQueryParameter.INCLUDE_STACKTRACE, "true");
-            pProcessingOptions.put(J4pQueryParameter.SERIALIZE_EXCEPTION,
-                    "true");
-            return j4pClient.execute(pRequest, "POST", pProcessingOptions);
-        } catch (J4pRemoteException e) {
-            tryToConvertException(e.getRemoteStackTrace(), e.getErrorValue());
-            throw new RuntimeException(e.getRemoteStackTrace(), e);
-        } catch (J4pException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    protected void tryToConvertException(String remoteStackTrace,
-            JSONObject errorValue) {
-        String conflictPrefix = ConflictingVersionException.class.getName()
-                + ": ";
-        if (remoteStackTrace.startsWith(conflictPrefix)) {
-            remoteStackTrace = remoteStackTrace.substring(conflictPrefix
-                    .length());
-            Pattern p = Pattern.compile("\r?\n");
-            remoteStackTrace = Arrays.asList(p.split(remoteStackTrace))
-                    .iterator().next();
-            throw new ConflictingVersionException(remoteStackTrace);
-        }
-        String validationExceptionPrefix = ValidationException.class.getName();
-        if (remoteStackTrace.startsWith(validationExceptionPrefix)) {
-            throw createValidationExceptionFromJSONObject(errorValue);
-        }
-    }
-
-    static ValidationException createValidationExceptionFromJSONObject(
-            JSONObject errorValue) {
-        String fValsKey = "failedValidations";
-        JSONObject failedVals = (JSONObject) errorValue.get(fValsKey);
-
-        checkArgument(
-                !failedVals.isEmpty(),
-                fValsKey + " was not present in received JSON: "
-                        + errorValue.toJSONString());
-        Map<String, Map<String, ExceptionMessageWithStackTrace>> failedValsMap = new HashMap<String, Map<String, ExceptionMessageWithStackTrace>>();
-
-        for (Object key : failedVals.keySet()) {
-            checkArgument(key instanceof String, "Unexpected key " + key
-                    + ", expected instance of String");
-            Map<String, ExceptionMessageWithStackTrace> innerMap = new HashMap<String, ValidationException.ExceptionMessageWithStackTrace>();
-            for (Object innerKey : ((JSONObject) failedVals.get(key)).keySet()) {
-                checkArgument(innerKey instanceof String, "Unexpected key "
-                        + innerKey + ", expected instance of String");
-                JSONObject exWithStackTraceVal = (JSONObject) (((JSONObject) failedVals
-                        .get(key)).get(innerKey));
-                Object mess = exWithStackTraceVal.get("message");
-                Object stack = exWithStackTraceVal.get("trace");
-                checkArgument(mess != null && stack != null,
-                        "\"Message\" and \"trace\" elements expected in received json: "
-                                + errorValue.toJSONString());
-                innerMap.put(innerKey.toString(),
-                        new ExceptionMessageWithStackTrace((String) mess,
-                                (String) stack));
-            }
-            failedValsMap.put((String) key, innerMap);
-        }
-        return new ValidationException(failedValsMap);
-    }
-
-    private static void checkArgument(boolean b, String string) {
-        if (b == false)
-            throw new IllegalArgumentException(string);
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public Map<String, AttributeEntry> getAttributes(ObjectName on) {
-        J4pListRequest req = new J4pListRequest(on);
-        J4pResponse<J4pListRequest> response = execute(req);
-        JSONObject listJSONResponse = response.getValue();
-        JSONObject attributes = (JSONObject) listJSONResponse.get("attr");
-
-        // Empty attributes list
-        if(attributes == null)
-            return Collections.emptyMap();
-
-        Map<String, JSONObject> listMap = new HashMap<>();
-
-        for (Object entryObject : attributes.entrySet()) {
-            Entry<String, Object> entry = (Entry<String, Object>) entryObject;
-            JSONObject entryVal = (JSONObject) entry.getValue();
-
-            // read value
-            listMap.put(entry.getKey(), entryVal);
-        }
-        J4pReadRequest j4pReadRequest = new J4pReadRequest(on, listMap.keySet()
-                .toArray(new String[0]));
-        J4pResponse<J4pReadRequest> readResponse = execute(j4pReadRequest);
-        Object readResponseValue = readResponse.getValue();
-        // readResponseValue can be String if there is just one attribute or
-        // JSONObject
-        Map<String, Object> attribsToValues = new HashMap<String, Object>();
-        if (readResponseValue instanceof JSONObject) {
-            JSONObject readJSONResponse = (JSONObject) readResponseValue;
-            for (Object entryObject : readJSONResponse.entrySet()) {
-                Entry<String, Object> entry = (Entry<String, Object>) entryObject;
-                String key = entry.getKey();
-                Object value = entry.getValue();
-                attribsToValues.put(key, value);
-            }
-        }
-
-        Map<String, AttributeEntry> resultMap = new HashMap<String, AttributeEntry>();
-        for (Entry<String, JSONObject> entry : listMap.entrySet()) {
-            String key = entry.getKey();
-            Object value = attribsToValues.size() > 0 ? attribsToValues
-                    .get(key) : readResponseValue;
-            JSONObject listJSON = entry.getValue();
-            String description = (String) listJSON.get("desc");
-            String type = (String) listJSON.get("type");
-            boolean rw = (Boolean) listJSON.get("rw");
-            AttributeEntry attributeEntry = new AttributeEntry(key,
-                    description, value, type, rw);
-            resultMap.put(key, attributeEntry);
-        }
-
-        return resultMap;
-    }
-
-    public String getConfigBeanDescripton(ObjectName on) {
-        J4pListRequest req = new J4pListRequest(on);
-        J4pResponse<J4pListRequest> response = execute(req);
-        JSONObject jsonDesc = response.getValue();
-        Object description = jsonDesc.get("desc");
-        return description == null ? null : description.toString();
-    }
-
-    protected List<ObjectName> jsonArrayToObjectNames(JSONArray jsonArray) {
-        List<ObjectName> result = new ArrayList<>(jsonArray.size());
-        for (Object entry : jsonArray) {
-            JSONObject jsonObject = (JSONObject) entry;
-            String objectNameString = (String) jsonObject.get("objectName");
-            try {
-                result.add(new ObjectName(objectNameString));
-            } catch (MalformedObjectNameException e) {
-                throw new IllegalStateException("Cannot convert "
-                        + objectNameString + " to ObjectName", e);
-            }
-        }
-        return result;
-    }
-
-    protected ObjectName extractObjectName(J4pResponse<J4pExecRequest> resp) {
-        JSONObject jsonResponse = resp.getValue();
-        return extractObjectName(jsonResponse);
-    }
-
-    protected ObjectName extractObjectName(JSONObject jsonResponse) {
-        String result = jsonResponse.get("objectName").toString();
-        return ObjectNameUtil.createON(result);
-    }
-
-    protected Set<ObjectName> lookupSomething(String signature,
-            Object[] parameters) {
-        J4pExecRequest req = new J4pExecRequest(objectName, signature,
-                parameters);
-        JSONArray jsonArray = execute(req).getValue();
-        return new HashSet<>(jsonArrayToObjectNames(jsonArray));
-    }
-
-    public Set<ObjectName> lookupConfigBeans() {
-        return lookupSomething("lookupConfigBeans()", new Object[0]);
-    }
-
-    public Set<ObjectName> lookupConfigBeans(String ifcName) {
-        return lookupSomething("lookupConfigBeans(java.lang.String)",
-                new Object[] { ifcName });
-    }
-
-    public Set<ObjectName> lookupConfigBeans(String ifcName, String instanceName) {
-        return lookupSomething(
-                "lookupConfigBeans(java.lang.String,java.lang.String)",
-                new Object[] { ifcName, instanceName });
-    }
-
-    public ObjectName lookupConfigBean(String ifcName, String instanceName)
-            throws InstanceNotFoundException {
-        J4pExecRequest req = new J4pExecRequest(objectName,
-                "lookupConfigBean(java.lang.String,java.lang.String)",
-                new Object[] { ifcName, instanceName });
-        try {
-            J4pResponse<J4pExecRequest> resp = execute(req);
-            return extractObjectName(resp);
-        } catch (RuntimeException e) {
-            if (e.getMessage() != null
-                    && e.getMessage().startsWith(
-                            InstanceNotFoundException.class.getName()))
-                throw new InstanceNotFoundException();
-            throw e;
-        }
-    }
-
-    public Set<String> getAvailableModuleNames() {
-        J4pReadRequest req = new J4pReadRequest(objectName,
-                "AvailableModuleNames");
-        List<String> value = execute(req).getValue();
-        return new HashSet<>(value);
-    }
-}
index 85397d2a20b311c40f03932ab5dd1442bba41db7..4c99c7770a4e3701719e9577fb5ccca7991c5924 100644 (file)
@@ -7,49 +7,38 @@
  */
 package org.opendaylight.controller.config.util;
 
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.junit.matchers.JUnitMatchers.containsString;
-
-import java.lang.management.ManagementFactory;
-import java.util.Set;
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConfigRegistry;
 
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
+import java.lang.management.ManagementFactory;
+import java.util.Set;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.config.api.ConfigRegistry;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.util.jolokia.ConfigRegistryJolokiaClient;
+import static org.junit.Assert.assertEquals;
 
 public class ConfigRegistryClientsTest {
 
-    private String jolokiaURL;
-
     private TestingConfigRegistry testingRegistry;
     private ObjectName testingRegistryON;
     private final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-    private ConfigRegistryClient jmxRegistryClient, jolokiaRegistryClient;
+    private ConfigRegistryClient jmxRegistryClient;
 
     @Before
     public void setUp() throws Exception {
-        jolokiaURL = JolokiaHelper.startTestingJolokia();
         testingRegistry = new TestingConfigRegistry();
         testingRegistryON = ConfigRegistry.OBJECT_NAME;
         mbs.registerMBean(testingRegistry, testingRegistryON);
         jmxRegistryClient = new ConfigRegistryJMXClient(
                 ManagementFactory.getPlatformMBeanServer());
-        jolokiaRegistryClient = new ConfigRegistryJolokiaClient(jolokiaURL);
     }
 
     @After
     public void cleanUp() throws Exception {
-        JolokiaHelper.stopJolokia();
         if (testingRegistryON != null) {
             mbs.unregisterMBean(testingRegistryON);
         }
@@ -58,8 +47,7 @@ public class ConfigRegistryClientsTest {
     @Test
     public void testLookupRuntimeBeans() throws Exception {
         Set<ObjectName> jmxLookup = lookupRuntimeBeans(jmxRegistryClient);
-        Set<ObjectName> jolokiaLookup = lookupRuntimeBeans(jolokiaRegistryClient);
-        assertEquals(jmxLookup, jolokiaLookup);
+        assertEquals(Sets.newHashSet(testingRegistry.run2, testingRegistry.run1, testingRegistry.run3), jmxLookup);
     }
 
     private Set<ObjectName> lookupRuntimeBeans(ConfigRegistryClient client)
@@ -79,28 +67,19 @@ public class ConfigRegistryClientsTest {
                 jmxRegistryClient, TestingConfigRegistry.moduleName1,
                 TestingConfigRegistry.instName1);
         assertEquals(1, jmxLookup.size());
-        Set<ObjectName> jolokiaLookup = clientLookupRuntimeBeansWithModuleAndInstance(
-                jolokiaRegistryClient, TestingConfigRegistry.moduleName1,
-                TestingConfigRegistry.instName1);
-        assertEquals(jmxLookup, jolokiaLookup);
+        assertEquals(Sets.newHashSet(testingRegistry.run2), jmxLookup);
 
         jmxLookup = clientLookupRuntimeBeansWithModuleAndInstance(
                 jmxRegistryClient, TestingConfigRegistry.moduleName2,
                 TestingConfigRegistry.instName2);
         assertEquals(1, jmxLookup.size());
-        jolokiaLookup = clientLookupRuntimeBeansWithModuleAndInstance(
-                jolokiaRegistryClient, TestingConfigRegistry.moduleName2,
-                TestingConfigRegistry.instName2);
-        assertEquals(jmxLookup, jolokiaLookup);
+        assertEquals(Sets.newHashSet(testingRegistry.run3), jmxLookup);
 
         jmxLookup = clientLookupRuntimeBeansWithModuleAndInstance(
                 jmxRegistryClient, TestingConfigRegistry.moduleName1,
                 TestingConfigRegistry.instName2);
         assertEquals(0, jmxLookup.size());
-        jolokiaLookup = clientLookupRuntimeBeansWithModuleAndInstance(
-                jolokiaRegistryClient, TestingConfigRegistry.moduleName1,
-                TestingConfigRegistry.instName2);
-        assertEquals(jmxLookup, jolokiaLookup);
+        assertEquals(Sets.newHashSet(), jmxLookup);
     }
 
     private Set<ObjectName> clientLookupRuntimeBeansWithModuleAndInstance(
@@ -112,29 +91,4 @@ public class ConfigRegistryClientsTest {
         }
         return beans;
     }
-
-    @Test
-    public void testValidationExceptionDeserialization() {
-        try {
-            jolokiaRegistryClient.commitConfig(null);
-            fail();
-        } catch (ValidationException e) {
-            String moduleName = "moduleName", instanceName = "instanceName";
-            assertThat(e.getFailedValidations().containsKey(moduleName),
-                    is(true));
-            assertThat(e.getFailedValidations().size(), is(1));
-            assertThat(e.getFailedValidations().get(moduleName).size(), is(1));
-            assertThat(
-                    e.getFailedValidations().get(moduleName)
-                            .containsKey(instanceName), is(true));
-            assertThat(
-                    e.getFailedValidations().get(moduleName).get(instanceName)
-                            .getMessage(), is("message"));
-            assertThat(
-                    e.getFailedValidations().get(moduleName).get(instanceName)
-                            .getTrace(),
-                    containsString("org.opendaylight.controller.config.util.TestingConfigRegistry.commitConfig"));
-        }
-    }
-
 }
index a6df1e91a5e5188e81137aae8284ab5ad6288d94..5ce6d467995f54be7a0644da658741d163515931 100644 (file)
@@ -7,47 +7,37 @@
  */
 package org.opendaylight.controller.config.util;
 
-import static org.junit.Assert.assertEquals;
-
-import java.lang.management.ManagementFactory;
-import java.util.Set;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
+import com.google.common.collect.Sets;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.util.jolokia.ConfigTransactionJolokiaClient;
 
-public class ConfigTransactionClientsTest {
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.lang.management.ManagementFactory;
+import java.util.Set;
 
+import static org.junit.Assert.assertEquals;
+
+public class ConfigTransactionClientsTest {
     private final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-    private String jolokiaURL;
-    private ConfigTransactionControllerMXBean transactionController;
+    private TestingConfigTransactionController transactionController;
     private ObjectName transactionControllerON;
-    private ConfigTransactionClient jmxTransactionClient,
-            jolokiaTransactionClient;
+    private ConfigTransactionClient jmxTransactionClient;
 
     @Before
     public void setUp() throws Exception {
-        jolokiaURL = JolokiaHelper.startTestingJolokia();
         transactionController = new TestingConfigTransactionController();
         transactionControllerON = new ObjectName(ObjectNameUtil.ON_DOMAIN + ":"
                 + ObjectNameUtil.TYPE_KEY + "=TransactionController");
         mbs.registerMBean(transactionController, transactionControllerON);
-        jmxTransactionClient = new ConfigTransactionJMXClient(null,
-                transactionControllerON,
+        jmxTransactionClient = new ConfigTransactionJMXClient(null, transactionControllerON,
                 ManagementFactory.getPlatformMBeanServer());
-        jolokiaTransactionClient = new ConfigTransactionJolokiaClient(
-                jolokiaURL, transactionControllerON, null);
     }
 
     @After
     public void cleanUp() throws Exception {
-        JolokiaHelper.stopJolokia();
         if (transactionControllerON != null) {
             mbs.unregisterMBean(transactionControllerON);
         }
@@ -56,8 +46,8 @@ public class ConfigTransactionClientsTest {
     @Test
     public void testLookupConfigBeans() throws Exception {
         Set<ObjectName> jmxLookup = testClientLookupConfigBeans(jmxTransactionClient);
-        Set<ObjectName> jolokiaLookup = testClientLookupConfigBeans(jolokiaTransactionClient);
-        assertEquals(jmxLookup, jolokiaLookup);
+        assertEquals(Sets.newHashSet(transactionController.conf1,
+                transactionController.conf2, transactionController.conf3), jmxLookup);
     }
 
     private Set<ObjectName> testClientLookupConfigBeans(
@@ -69,5 +59,4 @@ public class ConfigTransactionClientsTest {
         assertEquals(3, beans.size());
         return beans;
     }
-
 }
diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/JolokiaHelper.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/JolokiaHelper.java
deleted file mode 100644 (file)
index c0a2586..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.util;
-
-import org.jolokia.jvmagent.JolokiaServer;
-import org.jolokia.jvmagent.JvmAgentConfig;
-
-public class JolokiaHelper {
-    private static JolokiaServer jolokiaServer;
-
-    /**
-     * Bind to port 17777. By convention, ports above 10000 are used for testing
-     * and < 10000 for production
-     *
-     * @return url that can be passed to new J4pClient(url)
-     */
-    public static String startTestingJolokia() {
-        return startJolokia("localhost", 17777);
-    }
-
-    /**
-     * @return url that can be passed to new J4pClient(url)
-     * @throws IOException
-     */
-    public static String startJolokia(String host, int port) {
-        String agentArgs = "host=" + host + ",port=" + port;
-        JvmAgentConfig config = new JvmAgentConfig(agentArgs);
-        Exception lastException = null;
-        for (int i = 0; i < 10; i++) {
-            try {
-                jolokiaServer = new JolokiaServer(config, false);
-                jolokiaServer.start();
-                return "http://" + host + ":" + port + "/jolokia/";
-            } catch (Exception e) {
-                lastException = e;
-                try {
-                    Thread.sleep(100);
-                } catch (InterruptedException ie) {
-                    ie.printStackTrace();
-                }
-            }
-        }
-        throw new RuntimeException(lastException);
-    }
-
-    public static void stopJolokia() {
-        jolokiaServer.stop();
-    }
-}
index 07492043248718c10e2f686f2a8df1761ba633d5..4489762a47c7c83655201d3f357f2a9a15426ef7 100644 (file)
@@ -7,19 +7,8 @@
  */
 package org.opendaylight.controller.config.util;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.lang.management.ManagementFactory;
-import java.lang.reflect.Method;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -27,35 +16,40 @@ import org.opendaylight.controller.config.api.ConfigRegistry;
 import org.opendaylight.controller.config.api.LookupRegistry;
 import org.opendaylight.controller.config.api.jmx.ConfigTransactionControllerMXBean;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.util.jolokia.ConfigRegistryJolokiaClient;
-import org.opendaylight.controller.config.util.jolokia.ConfigTransactionJolokiaClient;
 
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Sets;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class LookupTest {
 
-    private String jolokiaURL;
     private TestingConfigRegistry testingRegistry;
     private ObjectName testingRegistryON;
     private final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-    private ConfigRegistryClient jmxRegistryClient, jolokiaRegistryClient;
+    private ConfigRegistryClient jmxRegistryClient;
     private ConfigTransactionControllerMXBean testingTransactionController;
     private ObjectName testingTransactionControllerON;
-    private ConfigTransactionClient jmxTransactionClient,
-            jolokiaTransactionClient;
+    private ConfigTransactionClient jmxTransactionClient;
 
     Map<LookupRegistry, ? extends Set<? extends LookupRegistry>> lookupProvidersToClients;
 
     @Before
     public void setUp() throws Exception {
-        jolokiaURL = JolokiaHelper.startTestingJolokia();
         testingRegistry = new TestingConfigRegistry();
         testingRegistryON = ConfigRegistry.OBJECT_NAME;
         mbs.registerMBean(testingRegistry, testingRegistryON);
         jmxRegistryClient = new ConfigRegistryJMXClient(
                 ManagementFactory.getPlatformMBeanServer());
-        jolokiaRegistryClient = new ConfigRegistryJolokiaClient(jolokiaURL);
+
 
         testingTransactionController = new TestingConfigTransactionController();
         testingTransactionControllerON = new ObjectName(
@@ -67,16 +61,15 @@ public class LookupTest {
         jmxTransactionClient = new ConfigTransactionJMXClient(null,
                 testingTransactionControllerON,
                 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);
+        HashSet<ConfigTransactionClient> configTransactionClients = Sets.newHashSet(jmxTransactionClient);
+        lookupProvidersToClients = ImmutableMap.of((LookupRegistry) testingRegistry, registryClients,
+                testingTransactionController, configTransactionClients);
     }
 
     @After
     public void cleanUp() throws Exception {
-        JolokiaHelper.stopJolokia();
         mbs.unregisterMBean(testingRegistryON);
         mbs.unregisterMBean(testingTransactionControllerON);
     }
index d4ae42d3de201c3102babd9e77e4e2b2918550d6..ba6262780c5767ae206a712a4eeb076b19832aaf 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 67e31b05e5f065e71639ad38d01759c8d8af6380..1c522f17b03803cf758829d5fd9a37472732b25d 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.util;
 
+import java.util.Map;
 import java.util.Set;
 
 import javax.management.InstanceAlreadyExistsException;
@@ -22,7 +23,7 @@ import com.google.common.collect.Sets;
 public class TestingConfigTransactionController implements
         ConfigTransactionControllerMXBean {
 
-    private final ObjectName conf1, conf2, conf3;
+    public final ObjectName conf1, conf2, conf3;
 
     public static final String moduleName1 = "moduleA";
     public static final String moduleName2 = "moduleB";
@@ -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();
+    }
 }
diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClientTest.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/jolokia/ListableJolokiaClientTest.java
deleted file mode 100644 (file)
index bff8006..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.util.jolokia;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.json.simple.JSONObject;
-import org.json.simple.JSONValue;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.config.api.ValidationException;
-import org.opendaylight.controller.config.api.ValidationException.ExceptionMessageWithStackTrace;
-
-public class ListableJolokiaClientTest {
-
-    private Map<String, Map<String, ExceptionMessageWithStackTrace>> failedValidations;
-
-    private ValidationException val;
-
-    private final static String ex = "{\"message\":null,"
-            + "\"failedValidations\":"
-            + "{\"ifc2\":{\"impl1\":{\"message\":\"abc\",\"trace\":\"vvv\"},"
-            + "\"impl2\":{\"message\":\"abc2\",\"trace\":\"vvv2\"}},"
-            + "\"ifc1\":"
-            + "{\"impl1\":{\"message\":\"abc\",\"trace\":\"vvv\"},"
-            + "\"impl2\":{\"message\":\"abc2\",\"trace\":\"vvv2\"}}},"
-            + "\"localizedMessage\":null," + "\"cause\":null}";
-
-    @Before
-    public void setUp() {
-        failedValidations = new HashMap<String, Map<String, ExceptionMessageWithStackTrace>>();
-        Map<String, ExceptionMessageWithStackTrace> map1 = new HashMap<String, ValidationException.ExceptionMessageWithStackTrace>();
-        map1.put("impl1", new ExceptionMessageWithStackTrace("abc", "vvv"));
-        map1.put("impl2", new ExceptionMessageWithStackTrace("abc2", "vvv2"));
-        failedValidations.put("ifc1", map1);
-        failedValidations.put("ifc2", map1);
-        val = new ValidationException(failedValidations);
-    }
-
-    @Test
-    public void testParsing() {
-        JSONObject e = (JSONObject) JSONValue.parse(ex);
-        ValidationException val2 = ListableJolokiaClient
-                .createValidationExceptionFromJSONObject(e);
-        assertThat(val2.getMessage(), is(val.getMessage()));
-        assertThat(val2.getFailedValidations(), is(val.getFailedValidations()));
-    }
-
-}
index 99437979de214aa4177d13f739f00f7e171f6210..9f0145fffe3e4b1d21ac25124b40aa017dba79b6 100644 (file)
@@ -63,7 +63,6 @@
         <osgi.version>5.0.0</osgi.version>
         <jacoco.version>0.6.2.201302030002</jacoco.version>
         <slf4j.version>1.7.2</slf4j.version>
-        <jolokia.version>1.1.1</jolokia.version>
         <opendaylight.yang.version>0.5.9-SNAPSHOT</opendaylight.yang.version>
         <opendaylight.binding.version>0.6.0-SNAPSHOT</opendaylight.binding.version>
         <opendaylight.yangtools.version>0.1.1-SNAPSHOT</opendaylight.yangtools.version>
                 <artifactId>guava</artifactId>
                 <version>14.0.1</version>
             </dependency>
-            <dependency>
-                <groupId>org.jolokia</groupId>
-                <artifactId>jolokia-core</artifactId>
-                <version>${jolokia.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.jolokia</groupId>
-                <artifactId>jolokia-jvm</artifactId>
-                <version>${jolokia.version}</version>
-                <classifier>agent</classifier>
-            </dependency>
-            <dependency>
-                <groupId>org.jolokia</groupId>
-                <artifactId>jolokia-client-java</artifactId>
-                <version>${jolokia.version}</version>
-            </dependency>
             <dependency>
                 <groupId>junit</groupId>
                 <artifactId>junit</artifactId>
index 5ec359ea8d842fbb3462debe30e85ebe3f616739..59368e8e498754b559096425c75eb0b45f5af058 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 a331e4e0c1ad95245f838ebee17192e2a7c61c81..37fd05bc5232eb85c51f0bc0c4e071f440e185d8 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 1945cac1c270919d10b59481139581e848c87f0a..3ef406694a6b12b7825f860e0130fbf20a1075dd 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,
index 4c0b81f7d71a4e4ce9a15c527050bfe23977740c..033d0573f9e43b641192856ae62675c5c91a7682 100644 (file)
       </dependencies>
     </profile>
     <profile>
+      <!-- sanitytests are only enabled with this profile -->
       <id>integrationtests</id>
       <activation>
         <activeByDefault>false</activeByDefault>
         <plugins>
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-dependency-plugin</artifactId>
-            <version>2.8</version>
-            <executions>
-              <execution>
-                <id>copy</id>
-                <phase>package</phase>
-                <goals>
-                  <goal>copy</goal>
-                </goals>
-              </execution>
-            </executions>
+            <artifactId>maven-invoker-plugin</artifactId>
+            <version>1.5</version>
             <configuration>
-              <artifactItems>
-                <artifactItem>
-                  <groupId>org.opendaylight.controller</groupId>
-                  <artifactId>sanitytest</artifactId>
-                  <version>${controller.version}</version>
-                  <type>jar</type>
-                </artifactItem>
-              </artifactItems>
-            </configuration>
-          </plugin>
-          <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>exec-maven-plugin</artifactId>
-            <version>1.2.1</version>
-            <executions>
-              <execution>
-                <id>sanity-test</id>
-                <phase>package</phase>
-                <goals>
-                  <goal>exec</goal>
-                </goals>
-              </execution>
-            </executions>
-            <configuration>
-              <executable>${java.home}/bin/java</executable>
-              <arguments>
-                <argument>-cp</argument>
-                <argument>./target/dependency/*</argument>
-                <argument>org.opendaylight.controller.distribution.Sanity</argument>
-              </arguments>
-              <environmentVariables>
-                <JAVA_HOME>
-                  ${java.home}
-                </JAVA_HOME>
-              </environmentVariables>
-            </configuration>
-          </plugin>
+              <debug>false</debug>
+              <projectsDirectory>../sanitytest</projectsDirectory>
+              <pomIncludes>
+                <pomInclude>pom.xml</pomInclude>
+              </pomIncludes>
+              <streamLogs>true</streamLogs>
+              <noLog>true</noLog>
+              <goals>
+                <goal>clean</goal>
+                <goal>verify</goal>
+              </goals>
+              </configuration>
+              <executions>
+                <execution>
+                  <id>integration-test</id>
+                    <goals>
+                      <goal>install</goal>
+                      <goal>run</goal>
+                    </goals>
+                </execution>
+              </executions>
+           </plugin>
         </plugins>
       </build>
+
+      <dependencies>
+        <dependency>
+         <groupId>org.opendaylight.controller</groupId>
+         <artifactId>controller-maven-plugin</artifactId>
+         <version>0.1.0-SNAPSHOT</version>
+        </dependency>
+      </dependencies>
     </profile>
   </profiles>
 
      <version>${commons.httpclient.version}</version>
     </dependency>
 
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sanitytest</artifactId>
-      <version>${controller.version}</version>
-    </dependency>
-
-
   </dependencies>
 
 
           </execution>
         </executions>
       </plugin>
+
     </plugins>
   </build>
+
 </project>
diff --git a/opendaylight/distribution/opendaylight/runsanity.bat b/opendaylight/distribution/opendaylight/runsanity.bat
deleted file mode 100644 (file)
index f219828..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-rem Inject the sanitytest jar as a controller plugin
-copy .\target\dependency\sanitytest*.jar .\target\distribution.opendaylight-osgipackage\opendaylight\plugins
-
-rem Store the current working directory in a variable so that we can get back to it later
-set cwd=%cd%
-
-rem Switch to the distribution folder
-cd .\target\distribution.opendaylight-osgipackage\opendaylight
-
-rem Run the controller
-cmd.exe /c run.bat
-
-rem Store the exit value of the controller in a variable
-set success=%ERRORLEVEL%
-
-rem Switch back to the directory from which this script was invoked
-cd %cwd%
-
-rem Remove the sanitytest jar from the plugins directory
-del .\target\distribution.opendaylight-osgipackage\opendaylight\plugins\sanitytest*.jar
-
-rem Exit using the exit code that we had captured earlier after running the controller
-exit /b %SUCCESS%
\ No newline at end of file
diff --git a/opendaylight/distribution/opendaylight/runsanity.sh b/opendaylight/distribution/opendaylight/runsanity.sh
deleted file mode 100755 (executable)
index 4ee9555..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# Inject the sanitytest jar as a controller plugin
-cp ./target/dependency/sanitytest*.jar ./target/distribution.opendaylight-osgipackage/opendaylight/plugins
-
-# Store the current working directory in a variable so that we can get back to it later
-cwd=`pwd`
-
-# Switch to the distribution folder
-cd ./target/distribution.opendaylight-osgipackage/opendaylight/
-
-# Run the controller
-./run.sh
-
-# Store the exit value of the controller in a variable
-success=`echo $?`
-
-# Switch back to the directory from which this script was invoked
-cd $cwd
-
-# Remove the sanitytest jar from the plugins directory
-rm ./target/distribution.opendaylight-osgipackage/opendaylight/plugins/sanitytest*.jar
-
-# Exit using the exit code that we had captured earlier after running the controller
-exit $success
-
index 8fea1756148cee4774de9a3586c7ea1056821e81..1e8f34e5b772cd845d3361fffdf71432a2c00958 100644 (file)
@@ -27,7 +27,6 @@
         <exclude>com.sun.jersey:jersey-json</exclude>
         <exclude>com.sun.jersey:jersey-server</exclude>
         <exclude>org.opendaylight.controller:logging.bridge</exclude>
-        <exclude>org.opendaylight.controller:sanitytest</exclude>
       </excludes>
       <outputFileNameMapping>
         ${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}
index fa33215ea6e9454d5c016e5e2f2fb58474099b55..edee185c172bc32a9169e7832b5bd3605579139f 100644 (file)
@@ -16,9 +16,9 @@
                <name>dom-broker</name>
                <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
-            <!-- to switch to the clustered data store, comment out the ref_hash-map-data-store <name> and uncomment the ref_cluster-data-store one -->
-            <name>ref_hash-map-data-store</name>
-            <!-- <name>ref_cluster-data-store</name> -->
+            <!-- to switch to the clustered data store, comment out the hash-map-data-store <name> and uncomment the cluster-data-store one -->
+            <name>hash-map-data-store</name>
+            <!-- <name>cluster-data-store</name> -->
                </data-store>
        </module>
        <module>
                <name>binding-broker-impl</name>
                <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
-                       <name>ref_binding-notification-broker</name>
+                       <name>binding-notification-broker</name>
                </notification-service>
                <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
-                       <name>ref_binding-data-broker</name>
+                       <name>binding-data-broker</name>
                </data-broker>
        </module>
        <module>
                <name>binding-data-broker</name>
                <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
                        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
-                       <name>ref_dom-broker</name>
+                       <name>dom-broker</name>
                </dom-broker>
                <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
                        <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
-                       <name>ref_runtime-mapping-singleton</name>
+                       <name>runtime-mapping-singleton</name>
                </mapping-service>
        </module>
 //SERVICES START
        <service>
                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
                <instance>
-                       <name>ref_yang-schema-service</name>
+                       <name>yang-schema-service</name>
                        <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
                <instance>
-                       <name>ref_binding-notification-broker</name>
+                       <name>binding-notification-broker</name>
                        <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-data-store</type>
                <instance>
-                       <name>ref_hash-map-data-store</name>
+                       <name>hash-map-data-store</name>
                        <provider>/modules/module[type='hash-map-data-store'][name='hash-map-data-store']</provider>
                </instance>
                <instance>
-                       <name>ref_cluster-data-store</name>
+                       <name>cluster-data-store</name>
                        <provider>/modules/module[type='dom-clustered-store-impl'][name='cluster-data-store']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
                <instance>
-                       <name>ref_binding-broker-impl</name>
+                       <name>binding-osgi-broker</name>
                        <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
                <instance>
-                       <name>ref_runtime-mapping-singleton</name>
+                       <name>runtime-mapping-singleton</name>
                        <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
                </instance>
        </service>
        <service>
        <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
                <instance>
-                       <name>ref_dom-broker</name>
+                       <name>dom-broker</name>
                        <provider>/modules/module[type='dom-broker-impl'][name='dom-broker']</provider>
                </instance>
        </service>
        <service>
                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
                <instance>
-                       <name>ref_binding-data-broker</name>
+                       <name>binding-data-broker</name>
                        <provider>/modules/module[type='binding-data-broker'][name='binding-data-broker']</provider>
                </instance>
        </service>
index 9d6ac8d1deaecdee57ef842335389edb9931e1d3..a8e33d26328876334205d0c7f8f679024eca6332 100644 (file)
@@ -140,7 +140,7 @@ SET RUN_CMD="%JAVA_HOME%\bin\java.exe" -Dopendaylight.controller %extraJVMOpts%
 ECHO %RUN_CMD%
 
 if "%startEnabled%" NEQ "" (
-    START /B cmd /C CALL %RUN_CMD% > %basedir%\logs\controller.out 2>&1
+    START /B cmd /C CALL %RUN_CMD%
     ECHO Running controller in the background.
 ) else (
     %RUN_CMD%
index 9d5ba5cc9596ee6b9986f905b1064bc9542f0f00..ce710d120e998b81cf3af602a434f4be5dc3f237 100644 (file)
 
   <artifactId>sanitytest</artifactId>
   <version>0.4.1-SNAPSHOT</version>
-  <packaging>bundle</packaging>
+  <packaging>jar</packaging>
+
+  <properties>
+    <distro.dir>${project.basedir}/../opendaylight/target/distribution.opendaylight-osgipackage/opendaylight</distro.dir>
+    <distro.script>${distro.dir}/run.bat</distro.script>
+    <!-- the address is passed to both the controller & the test to establish the connection -->
+    <sanitytest.bind.address>127.0.0.1</sanitytest.bind.address>
+    <sanitytest.timeout>300</sanitytest.timeout>
+  </properties>
+
+  <profiles>
+    <profile>
+      <id>non-windows</id>
+      <activation>
+        <os>
+          <family>!windows</family>
+        </os>
+      </activation>
+      <properties>
+        <distro.script>${distro.dir}/run.sh</distro.script>
+        <distro.pid>/tmp/opendaylight.PID</distro.pid>
+      </properties>
+    </profile>
+  </profiles>
+
   <dependencies>
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
       <scope>provided</scope>
     </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.ow2.chameleon.management</groupId>
+      <artifactId>chameleon-mbeans</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
+
   <build>
     <plugins>
       <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <version>${bundle.plugin.version}</version>
-        <extensions>true</extensions>
+        <!-- disable the install plugin -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <version>${install.plugin.version}</version>
         <configuration>
-          <instructions>
-            <Export-Package>
-              org.opendaylight.controller.sanitytest
-            </Export-Package>
-            <Import-Package>
-              javax.xml.bind.annotation,
-              org.osgi.service.component,
-              org.slf4j,
-              org.eclipse.osgi.framework.console,
-              org.osgi.framework,
-              org.eclipse.osgi.baseadaptor,
-              org.eclipse.osgi.framework.adaptor,
-              org.osgi.framework.wiring
-            </Import-Package>
-            <Bundle-Activator>
-              org.opendaylight.controller.sanitytest.internal.Activator
-            </Bundle-Activator>
-          </instructions>
-          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+          <skip>true</skip>
         </configuration>
+        <executions>
+          <execution>
+            <id>default-install</id>
+            <phase>none</phase>
+          </execution>
+        </executions>
       </plugin>
+
+      <plugin>
+        <!--  ensure that the distro installation is already built -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>${enforcer.plugin.version}</version>
+        <executions>
+          <execution>
+            <id>enforce-files-exist</id>
+            <phase>pre-integration-test</phase>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <requireFilesExist>
+                  <files>
+                    <file>${distro.script}</file>
+                  </files>
+                </requireFilesExist>
+              </rules>
+              <fail>true</fail>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>controller-maven-plugin</artifactId>
+        <version>0.1.0-SNAPSHOT</version>
+          <configuration>
+              <controllerHome>${distro.dir}</controllerHome>
+              <controllerHost>localhost</controllerHost>
+              <controllerWebPort>8080</controllerWebPort>
+              <controllerUsername>admin</controllerUsername>
+              <controllerPassword>admin</controllerPassword>
+              <controllerStartScriptName>${distro.script}</controllerStartScriptName>
+              <pidFile>${distro.pid}</pidFile>
+          </configuration>
+        <executions>
+          <execution>
+            <!-- ensure controller is started in pre-integration phase -->
+            <id>start-controller</id>
+            <phase>pre-integration-test</phase>
+            <configuration>
+              <startArgs>
+                <param>-start</param>
+                <param>-jmx</param>
+                <param>-Djava.rmi.server.hostname=${sanitytest.bind.address} </param>
+              </startArgs>
+              <warmupTimeSecs> 60 </warmupTimeSecs>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+          <execution>
+            <!-- ensure controller is stopped in post-integration phase -->
+            <id>stop-controller</id>
+            <phase>post-integration-test</phase>
+            <goals>
+              <goal>stop</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <!--  run the test -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+        <version>${failsafe.version}</version>
+        <configuration>
+          <systemPropertyVariables>
+            <ctrl.home>${distro.dir}</ctrl.home>
+            <ctrl.host>${sanitytest.bind.address}</ctrl.host>
+            <ctrl.start.timeout>${sanitytest.timeout}</ctrl.start.timeout>
+          </systemPropertyVariables>
+        </configuration>
+      </plugin>
+
     </plugins>
+
+
   </build>
 </project>
diff --git a/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/distribution/Sanity.java b/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/distribution/Sanity.java
deleted file mode 100644 (file)
index 7fc25e2..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.opendaylight.controller.distribution;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Sanity {
-
-    static void copy(InputStream in, OutputStream out) throws IOException {
-      while (true) {
-        int c = in.read();
-        if (c == -1) break;
-        out.write((char)c);
-      }
-    }
-
-    public static void main(String[] args) throws IOException, InterruptedException {
-        String cwd = System.getProperty("user.dir");
-
-        System.out.println("Current working directory = " + cwd);
-
-        String os = System.getProperty("os.name").toLowerCase();
-        List<String> script = new ArrayList<String>();
-
-        if(os.contains("windows")){
-            script.add("cmd.exe");
-            script.add("/c");
-            script.add("runsanity.bat");
-        } else {
-            script.add("./runsanity.sh");
-        }
-
-        ProcessBuilder processBuilder = new ProcessBuilder();
-        processBuilder.inheritIO().command(script);
-        Process p = processBuilder.start();
-
-        copy(p.getInputStream(), System.out);
-
-        p.waitFor();
-
-        System.out.println("Test exited with exitValue = " + p.exitValue());
-
-        System.exit(p.exitValue());
-    }
-}
diff --git a/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/sanitytest/internal/Activator.java b/opendaylight/distribution/sanitytest/src/main/java/org/opendaylight/controller/sanitytest/internal/Activator.java
deleted file mode 100644 (file)
index 08f0700..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-package org.opendaylight.controller.sanitytest.internal;
-
-import java.util.Timer;
-import java.util.TimerTask;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleRevision;
-
-public class Activator implements BundleActivator {
-    //10 Second initial, 1 second subsequent
-    private static final int INITIAL_DELAY = 10000;
-    private static final int SUBSEQUENT_DELAY = 1000;
-    private static final int MAX_ATTEMPTS = 120;
-
-
-    private String stateToString(int state) {
-        switch (state) {
-        case Bundle.ACTIVE:
-            return "ACTIVE";
-        case Bundle.INSTALLED:
-            return "INSTALLED";
-        case Bundle.RESOLVED:
-            return "RESOLVED";
-        case Bundle.UNINSTALLED:
-            return "UNINSTALLED";
-        case Bundle.STARTING:
-            return "STARTING";
-        default:
-            return "Not CONVERTED: state value is " + state;
-        }
-    }
-
-    public void start(final BundleContext bundleContext) throws Exception {
-        Timer monitorTimer = new Timer("monitor timer", true);
-        monitorTimer.schedule(new TimerTask() {
-            @Override
-            public void run() {
-                int countup = 0;
-                boolean failed = false;
-                boolean resolved = false;
-                while (!resolved) {
-                    resolved = true;
-                    failed = false;
-                    for(Bundle bundle : bundleContext.getBundles()){
-                        /*
-                         * A bundle should be ACTIVE, unless it a fragment, in which case it should be RESOLVED
-                         */
-                        int state = bundle.getState();
-                        if ((bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
-                            //fragment
-                            if (state != Bundle.RESOLVED) {
-                                System.out.println("------ Failed to activate/resolve fragment = " + bundle.getSymbolicName() + " state = " + stateToString(bundle.getState()));
-                                failed = true;
-                                if (state == Bundle.STARTING)
-                                    resolved = false;
-                            }
-                        } else {
-                            if(state != Bundle.ACTIVE) {
-                                System.out.println("------ Failed to activate/resolve bundle = " + bundle.getSymbolicName() + " state = " + stateToString(bundle.getState()));
-                                failed = true;
-                                if (state == Bundle.STARTING)
-                                    resolved = false;
-                            }
-                        }
-                    }
-                    if (!resolved) {
-                        countup++;
-                        if (countup < MAX_ATTEMPTS) {
-                            System.out.println("all bundles haven't finished starting, will repeat");
-                            try {
-                                Thread.sleep(SUBSEQUENT_DELAY);
-                            } catch (Exception e) {
-                                System.out.println("Thread.sleep interuptted.");
-                                break;
-                            }
-                        } else
-                            resolved = true;
-                    }
-                }
-
-                if(failed){
-                    System.out.flush();
-                    System.out.println("exiting with 1 as failed");
-                    System.out.close();
-                    Runtime.getRuntime().exit(1);
-                } else {
-                    System.out.flush();
-                    System.out.println("exiting with 0 as succeeded");
-                    System.out.close();
-                    Runtime.getRuntime().exit(0);
-                }
-            }
-        }, INITIAL_DELAY);
-    }
-
-    public void stop(BundleContext bundleContext) throws Exception {
-
-    }
-}
diff --git a/opendaylight/distribution/sanitytest/src/test/java/org/opendaylight/controller/distribution/test/SanityIT.java b/opendaylight/distribution/sanitytest/src/test/java/org/opendaylight/controller/distribution/test/SanityIT.java
new file mode 100644 (file)
index 0000000..931e88f
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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.distribution.test;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.Socket;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+
+import javax.management.JMX;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.ow2.chameleon.management.beans.BundleMXBean;
+import org.ow2.chameleon.management.beans.OSGiPlatformMXBean;
+
+/**
+ * This integration test assumes a running local controller. The test does the
+ * following:
+ * 1) Wait for HTTP, JMX and OF ports to open
+ * 2) Establishes a JMX connection and registers a bundle notification listener
+ * 3) Waits till all bundles reach expected states or the timeout period elapses
+ */
+public class SanityIT {
+  private static final int OF_PORT = Integer.getInteger("ctrl.of.port", 6633);
+  private static final int HTTP_PORT = Integer.getInteger("ctrl.http.port", 8080);
+  private static final int JMX_PORT = Integer.getInteger("ctrl.jmx.port", 1088);
+  private static final int RMI_PORT = Integer.getInteger("ctrl.rmi.port", 1099);
+  private static final String CTRL_HOST = System.getProperty("ctrl.host", "127.0.0.1");
+  private static final String CTRL_HOME = System.getProperty("ctrl.home");
+  private static final long TIMEOUT_MILLIS =
+          Integer.getInteger("ctrl.start.timeout", 3*60) * 1000L;
+  private static final String JMX_URL =
+          "service:jmx:rmi:///jndi/rmi://" + CTRL_HOST + ":" + JMX_PORT + "/jmxrmi";
+
+  private static final Set<String> bundles =
+          Collections.synchronizedSet(new HashSet<String>());
+  private static final Set<String> fragments =
+          Collections.synchronizedSet(new HashSet<String>());
+
+  @BeforeClass
+  public static void loadBundles() throws IOException {
+      log("         ctrl.home: " + CTRL_HOME);
+      log("         ctrl.host: " + CTRL_HOST);
+      log("ctrl.start.timeout: " + TIMEOUT_MILLIS);
+      log("           jmx.url: " + JMX_URL);
+
+      Assert.assertNotNull(CTRL_HOME);
+      File ctrlHome = new File(CTRL_HOME);
+      Assert.assertTrue(ctrlHome.exists() && ctrlHome.isDirectory());
+      File configDir = new File(ctrlHome, "configuration");
+      Assert.assertTrue(configDir.exists() && configDir.isDirectory());
+      File configIni = new File(configDir, "config.ini");
+      Assert.assertTrue(configIni.exists());
+      Properties config = new Properties();
+      config.load(new FileInputStream(configIni));
+      processBundles(configDir, config.getProperty("osgi.bundles"));
+      processBundles(new File(ctrlHome, "plugins"));
+      log("Bundles found in installation:   " + bundles.size());
+      log("Fragments found in installation: " + fragments.size());
+  }
+
+@Test
+  public void sanityTest() throws Exception {
+    // wait for http, jmx & of ports to open
+    long startTime = System.currentTimeMillis();
+    waitForListening(OF_PORT, false, startTime);
+    waitForListening(JMX_PORT, false, startTime);
+    waitForListening(HTTP_PORT, false, startTime);
+
+    // open jmx connection
+    JMXServiceURL serviceUrl = new JMXServiceURL(JMX_URL);
+    JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceUrl, null);
+    final MBeanServerConnection conn = jmxConnector.getMBeanServerConnection();
+
+    ObjectName fmkName = new ObjectName("org.ow2.chameleon:type=framework");
+    OSGiPlatformMXBean fmkBean= JMX.newMBeanProxy(conn, fmkName,
+              OSGiPlatformMXBean.class, true);
+    conn.addNotificationListener(fmkName, new NotificationListener() {
+
+        @Override
+        public void handleNotification(Notification n, Object handback) {
+            try {
+                //log("Notification: source: " + n.getSource());
+                ObjectName bundleName = new ObjectName(
+                        "org.ow2.chameleon:type=bundle,id=" + n.getUserData());
+                BundleMXBean bundleBean = JMX.newMXBeanProxy(conn,
+                        bundleName, BundleMXBean.class, true);
+                log("Bundle state change: " + bundleBean.getSymbolicName() +
+                        " : " + stateToString(bundleBean.getState()));
+                handleBundleEvent(bundleBean);
+                // if its a system bundle, notify the main thread
+                if (bundleBean.getBundleId() == 0 &&
+                        bundleBean.getState() == Bundle.ACTIVE)
+                {
+                    synchronized(SanityIT.this) {
+                        SanityIT.this.notify();
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }, null, null);
+
+    if (checkAllBundles(conn) > 0) {
+        log("Waiting for system bundle to start... (times out in: " + TIMEOUT_MILLIS + "ms)");
+        long timeElapsed = System.currentTimeMillis() - startTime;
+        synchronized(this) {
+            this.wait(TIMEOUT_MILLIS - timeElapsed);
+        }
+        log("System bundle started. Revalidating bundle states for all bundles...");
+
+        // Sometimes, the system bundle starts earlier than other bundles(?). The
+        // following loop will cover that case.
+        do {
+            Thread.sleep(2000); // 2s seems appropriate given the default timeout
+            if (checkAllBundles(conn) == 0) {
+                break;
+            }
+        } while(System.currentTimeMillis() - startTime < TIMEOUT_MILLIS);
+    }
+    try {
+        jmxConnector.close();
+    } catch (Exception ignore) {
+        // dont want the tests to fail in case we can't close jmx connection
+        ignore.printStackTrace();
+    }
+    if (bundles.size() + fragments.size() == 0) {
+        log("All bundles have reached expected state");
+    } else {
+        log("The following bundles did not reach expected state: ");
+        for (String s : bundles) log("Bundle: " + s);
+        for (String s : fragments) log("Fragment: " + s);
+
+    }
+    Assert.assertTrue(bundles.size() == 0 && fragments.size() == 0);
+  }
+
+  private static int checkAllBundles(MBeanServerConnection conn) throws Exception {
+      ObjectName allBundlesName = new ObjectName("org.ow2.chameleon:*");
+      Set<ObjectName> bundleNames = conn.queryNames(allBundlesName, null);
+      for (ObjectName bundleName : bundleNames) {
+          if ("bundle".equals(bundleName.getKeyProperty("type"))) {
+              BundleMXBean bundleBean = JMX.newMBeanProxy(conn, bundleName,
+                      BundleMXBean.class, true);
+              handleBundleEvent(bundleBean);
+          }
+      }
+      int remaining = bundles.size() + fragments.size();
+      if (remaining > 0) {
+        log("Bundles not in expected states: " + remaining + " Waiting...");
+      }
+      return remaining;
+  }
+
+  private synchronized static void handleBundleEvent(BundleMXBean bundleBean) {
+      String name = bundleBean.getSymbolicName();
+      int state = bundleBean.getState();
+      // BUG in BundleMXBeanImpl - can't get bundle headers :(
+      // String fragHost = bundleBean.getBundleHeaders().get(Constants.FRAGMENT_HOST);
+      if (bundles.contains(name) && (state == Bundle.RESOLVED || state == Bundle.ACTIVE)) {
+          bundles.remove(name);
+      } else if (fragments.contains(name) && state == Bundle.RESOLVED) {
+          fragments.remove(name);
+      }
+      //log("Bundles to be started: " + bundles.size());
+  }
+
+
+  //    reference\:file\:../lib/org.apache.felix.fileinstall-3.1.6.jar@1:start,\
+  private static void processBundles(File dir, String property) {
+      Assert.assertTrue(property == null || property.length() > 0);
+      for(String s : property.split(",")) {
+          int idx = s.indexOf("@");
+          s = s.substring(15, (idx == -1 ? s.length() : idx));
+          if (!s.endsWith(".jar")) s = s + ".jar";
+          processJar(new File(dir, s));
+      }
+  }
+
+  public static void processBundles(File dir) throws IOException {
+      if (!dir.exists()) throw new FileNotFoundException("Cannot find dir:" + dir);
+      dir.listFiles(new FileFilter() {
+
+        @Override
+        public boolean accept(File file) {
+            //p("---- " + file);
+            if (file.getName().endsWith(".jar")) {
+                return processJar(file);
+            }
+            return false;
+        }
+      });
+  }
+
+  public static boolean processJar(File file) {
+      try {
+          //log("----" + file);
+          JarFile jar = new JarFile(file, false);
+          Attributes jarAttributes = jar.getManifest().getMainAttributes();
+          String bundleName = jarAttributes.getValue(Constants.BUNDLE_SYMBOLICNAME);
+          String fragHost = jarAttributes.getValue(Constants.FRAGMENT_HOST);
+          if (bundleName == null) {
+              log("Found a non bundle file:" + file);
+              return false;
+          } else {
+              int idx = bundleName.indexOf(';');
+              if (idx > -1) {
+                  bundleName = bundleName.substring(0, idx);
+              }
+          }
+
+          if (fragHost == null) {
+              if (!bundles.add(bundleName)) {
+                  throw new IllegalStateException(
+                          "Found duplicate bundles with same symbolic name: "
+                                  + bundleName);
+              }
+          } else {
+              // fragments attaching to framework can't be detected
+              if (fragHost.contains("extension:=\"framework\"")) return false;
+              if (!fragments.add(bundleName)) {
+                  throw new IllegalStateException(
+                          "Found duplicate fragments with same symbolic name: "
+                                  + bundleName);
+              }
+          }
+      } catch (IOException e) {
+          throw new IllegalStateException("Error processing jar: " + file , e);
+      }
+      return true;
+  }
+
+    public static long waitForListening(int port, boolean isHTTP, long beginTime)
+            throws InterruptedException {
+        long timeElapsedMillis = System.currentTimeMillis() - beginTime;
+        long sleepTimeMillis = 500L; // 0.5 secs
+
+        while (timeElapsedMillis < TIMEOUT_MILLIS) {
+            long timeRemaining = TIMEOUT_MILLIS - timeElapsedMillis;
+            sleepTimeMillis *= 2; // exponential backoff
+            long toSleep = (sleepTimeMillis > timeRemaining)
+                    ? timeRemaining : sleepTimeMillis;
+            Thread.sleep(toSleep);
+            timeElapsedMillis = System.currentTimeMillis() - beginTime;
+            if (isHTTP ? connectHTTP(port) : connectTCP(port)) {
+              log("Port is open: " + port);
+              return timeElapsedMillis;
+            }
+        }
+        throw new IllegalStateException("Timeout waiting for port: " + port);
+    }
+
+    private static void log(String msg) {
+        System.out.format("[SanityIT] [%s] %s %s", new Date().toString(), msg,
+                System.lineSeparator());
+    }
+
+    public static boolean connectTCP(int port) {
+      String host = CTRL_HOST.length() == 0 ? null : CTRL_HOST;
+      try {
+        Socket sock = new Socket(host, port);
+        sock.getPort();
+        try {
+          sock.close();
+        } catch (IOException ignore) {
+          // Can't close socket. Ingore and let downstream validate health
+        }
+        return true;
+      } catch (IOException ioe) {
+        return false;
+      }
+    }
+
+    public static boolean connectHTTP(int port) {
+        String host = CTRL_HOST.length() == 0 ? "localhost" : CTRL_HOST;
+        try {
+            URL url = new URL("http", host, port, "/");
+            HttpURLConnection con;
+            con = (HttpURLConnection) url.openConnection();
+            return (con.getResponseCode() > 0);
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    private String stateToString(int state) {
+        switch (state) {
+            case Bundle.ACTIVE: return "ACTIVE";
+            case Bundle.INSTALLED: return "INSTALLED";
+            case Bundle.RESOLVED: return "RESOLVED";
+            case Bundle.UNINSTALLED: return "UNINSTALLED";
+            case Bundle.STARTING: return "STARTING";
+            case Bundle.STOPPING: return "STOPPING";
+            default: return "UNKNOWN: " + state;
+        }
+    }
+
+
+
+
+}
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributesConstants.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributesConstants.java
new file mode 100644 (file)
index 0000000..4f9e1fe
--- /dev/null
@@ -0,0 +1,17 @@
+/**
+ * @author Maros Marsalek
+ *
+ * 12 2013
+ *
+ * Copyright (c) 2012 by Cisco Systems, Inc.
+ * All rights reserved.
+ */
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes;
+
+public class AttributesConstants {
+
+    /**
+     * Property placed into object names for dependencies to preserve reference name
+     */
+    public static final String REF_NAME_ON_PROPERTY_KEY = "X-refName";
+}
index f4d88c7c8e371e0bbc8fd8614c76b79bc69a7a50..842634163607315bd018d00d43c29b1db2dd83d0 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributesConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
 
@@ -42,7 +43,11 @@ public class ObjectNameAttributeMappingStrategy extends
         Util.checkType(value, ObjectName.class);
 
         ObjectName on = (ObjectName) value;
-        String refName = tracker.addServiceEntry(namespace, serviceName, on);
+
+        String expectedRefName = on.getKeyProperty(AttributesConstants.REF_NAME_ON_PROPERTY_KEY);
+
+        String refName = expectedRefName == null ? tracker.getRefName(namespace, serviceName, on, Optional.<String> absent())
+                : tracker.getRefName(namespace, serviceName, on, Optional.of(expectedRefName));
 
         return Optional.of(new MappedDependency(namespace, serviceName, refName));
     }
index c6f306b3605cdc83652efd36e53cca6bb9b9f446..d8f0e2357ea0fb57063121b2758aca908b553eb5 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 
 import com.google.common.base.Optional;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributesConstants;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.mapping.ObjectNameAttributeMappingStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services.ServiceInstance;
@@ -46,6 +47,8 @@ public class ObjectNameAttributeResolvingStrategy extends AbstractAttributeResol
 
         ServiceInstance byRefName = serviceTracker.getByServiceAndRefName(namespace, serviceName, refName);
         ObjectName on = ObjectNameUtil.createReadOnlyModuleON(byRefName.getModuleName(), byRefName.getInstanceName());
+        on = ObjectNameUtil.createON(on.toString() + "," + AttributesConstants.REF_NAME_ON_PROPERTY_KEY + "=" + refName);
+
         logger.debug("Attribute {} : {} parsed to type {}", attrName, value, getOpenType());
         return Optional.of(on);
     }
index f33a32271fd189dd39a61b7403069d765e4d1615..3a5fa1170fec28922155e8e7b2748eb7393448b5 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -53,7 +54,7 @@ public class Config {
     }
 
     public static Map<String, Map<String, Collection<ObjectName>>> getMappedInstances(Set<ObjectName> instancesToMap,
-                                                                                Services serviceTracker, Map<String, Map<String, ModuleConfig>> configs) {
+                                                                                Map<String, Map<String, ModuleConfig>> configs) {
         Multimap<String, ObjectName> moduleToInstances = mapInstancesToModules(instancesToMap);
 
         Map<String, Map<String, Collection<ObjectName>>> retVal = Maps.newLinkedHashMap();
@@ -75,13 +76,6 @@ public class Config {
 
                 innerRetVal.put(moduleName, instances);
 
-                // All found instances add to service tracker in advance
-                // This way all instances will be serialized as all available
-                // services when get-config is triggered
-                // (even if they are not used as services by other instances)
-                // = more user friendly
-                addServices(serviceTracker, instances, mbeEntry.getValue().getProvidedServices());
-
             }
 
             retVal.put(namespace, innerRetVal);
@@ -89,15 +83,6 @@ public class Config {
         return retVal;
     }
 
-    private static void addServices(Services serviceTracker, Collection<ObjectName> instances,
-            Multimap<String, String> providedServices) {
-        for (ObjectName instanceOn : instances) {
-            for (Entry<String, String> serviceName : providedServices.entries()) {
-                serviceTracker.addServiceEntry(serviceName.getKey(), serviceName.getValue(), instanceOn);
-            }
-        }
-    }
-
     private static Multimap<String, ObjectName> mapInstancesToModules(Set<ObjectName> instancesToMap) {
         Multimap<String, ObjectName> retVal = HashMultimap.create();
 
@@ -114,11 +99,10 @@ public class Config {
     // }
 
     public Element toXml(Set<ObjectName> instancesToMap, Optional<String> maybeNamespace, Document document,
-            Element dataElement) {
-        Services serviceTracker = new Services();
+            Element dataElement, Services serviceTracker) {
 
         Map<String, Map<String, Collection<ObjectName>>> moduleToInstances = getMappedInstances(instancesToMap,
-                serviceTracker, moduleConfigs);
+                moduleConfigs);
 
         Element root = dataElement;
         if (maybeNamespace.isPresent()) {
@@ -167,13 +151,13 @@ public class Config {
     // TODO refactor, replace string representing namespace with namespace class
     // TODO refactor, replace Map->Multimap with e.g. ConfigElementResolved
     // class
-    public Map<String, Multimap<String, ModuleElementResolved>> fromXml(XmlElement xml, Set<ObjectName> instancesForFillingServiceRefMapping,
-                                                                        EditStrategyType defaultEditStrategyType) {
+    public ConfigElementResolved fromXml(XmlElement xml,
+                                         EditStrategyType defaultEditStrategyType, ServiceReferenceReadableRegistry taClient) {
         Map<String, Multimap<String, ModuleElementResolved>> retVal = Maps.newHashMap();
 
         List<XmlElement> recognisedChildren = Lists.newArrayList();
 
-        Services serviceTracker = fromXmlServices(xml, recognisedChildren, instancesForFillingServiceRefMapping);
+        Services serviceTracker = fromXmlServices(xml, recognisedChildren, taClient);
         List<XmlElement> moduleElements = fromXmlModules(xml, recognisedChildren);
 
         xml.checkUnrecognisedElements(recognisedChildren);
@@ -182,7 +166,26 @@ public class Config {
             resolveModule(retVal, serviceTracker, moduleElement, defaultEditStrategyType);
         }
 
-        return retVal;
+        return new ConfigElementResolved(retVal, serviceTracker);
+    }
+
+    public static class ConfigElementResolved {
+
+        private final Map<String, Multimap<String, ModuleElementResolved>> resolvedModules;
+        private final Services services;
+
+        public ConfigElementResolved(Map<String, Multimap<String, ModuleElementResolved>> retVal, Services serviceTracker) {
+            this.resolvedModules = retVal;
+            this.services = serviceTracker;
+        }
+
+        public Map<String, Multimap<String, ModuleElementResolved>> getResolvedModules() {
+            return resolvedModules;
+        }
+
+        public Services getServices() {
+            return services;
+        }
     }
 
     private List<XmlElement> fromXmlModules(XmlElement xml, List<XmlElement> recognisedChildren) {
@@ -224,7 +227,8 @@ public class Config {
         innerMap.put(factoryName, moduleElementResolved);
     }
 
-    private Services fromXmlServices(XmlElement xml, List<XmlElement> recognisedChildren, Set<ObjectName> instancesForFillingServiceRefMapping) {
+    private Services fromXmlServices(XmlElement xml, List<XmlElement> recognisedChildren,
+                                     ServiceReferenceReadableRegistry taClient) {
         Optional<XmlElement> servicesElement = xml.getOnlyChildElementOptionally(XmlNetconfConstants.SERVICES_KEY,
                 XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG);
 
@@ -235,22 +239,7 @@ public class Config {
         } else {
             mappedServices = new HashMap<>();
         }
-        Services services = Services.resolveServices(mappedServices);
-        // merge with what candidate db contains by default - ref_
-
-        for(ObjectName existingON: instancesForFillingServiceRefMapping) {
-            logger.trace("Filling services from {}", existingON);
-            // get all its services
-            String factoryName = ObjectNameUtil.getFactoryName(existingON);
-            ModuleConfig moduleConfig = moduleNamesToConfigs.get(factoryName);
-
-            checkState(moduleConfig != null, "Cannot find ModuleConfig with name " + factoryName + " in " + moduleNamesToConfigs);
-            // Set<String> services = ;
-            for (Entry<String, String> serviceName : moduleConfig.getProvidedServices().entries()) {
-
-                services.addServiceEntry(serviceName.getKey(), serviceName.getValue(), existingON);
-            }
-        }
+        Services services = Services.resolveServices(mappedServices, taClient);
 
         return services;
     }
index 33858746cb0f06bdd4d7387ad8141f29a6d23b51..aae1636165c07c6822fbadf10ddfeafad2d28653 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
@@ -128,7 +129,7 @@ public final class InstanceConfig {
     }
 
     public InstanceConfigElementResolved fromXml(XmlElement moduleElement, Services services, String moduleNamespace,
-                                                 EditStrategyType defaultStrategy) {
+            EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
         Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
 
         Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
@@ -153,7 +154,7 @@ public final class InstanceConfig {
                 XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
 
         InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved(
-                retVal, defaultStrategy) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy);
+                retVal, defaultStrategy, providedServices) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy, providedServices);
 
         resolveConfiguration(instanceConfigElementResolved, services);
         return instanceConfigElementResolved;
index e4bd9212e90995ae7515026c49815645afe6ff3e..55cb60bed5e7df0268908b160650ecd46101e137 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Multimap;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigStrategy;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser;
@@ -24,16 +25,19 @@ public class InstanceConfigElementResolved {
 
     private final EditStrategyType editStrategy;
     private final Map<String, AttributeConfigElement> configuration;
+    private final Multimap<String, String> providedServices;
 
-    public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy) {
+    public InstanceConfigElementResolved(String currentStrategy, Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
         EditStrategyType valueOf = checkStrategy(currentStrategy, defaultStrategy);
         this.editStrategy = valueOf;
         this.configuration = configuration;
+        this.providedServices = providedServices;
     }
 
-    public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy) {
+    public InstanceConfigElementResolved(Map<String, AttributeConfigElement> configuration, EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
         editStrategy = defaultStrategy;
         this.configuration = configuration;
+        this.providedServices = providedServices;
     }
 
 
@@ -54,7 +58,7 @@ public class InstanceConfigElementResolved {
 
 
     public EditConfigStrategy getEditStrategy() {
-        return editStrategy.getFittingStrategy();
+        return editStrategy.getFittingStrategy(providedServices);
     }
 
     public Map<String, AttributeConfigElement> getConfiguration() {
index 2e2a26400f19899b3f172e80f0de00f7c46ce1c6..2ac6fe0a9bb650116e5f3591fb35cdf8655ee311 100644 (file)
@@ -87,7 +87,7 @@ public class ModuleConfig {
     public ModuleElementResolved fromXml(XmlElement moduleElement, Services depTracker, String instanceName,
             String moduleNamespace, EditStrategyType defaultStrategy) {
 
-        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy);
+        InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices);
         return new ModuleElementResolved(instanceName, ice);
     }
 
index f522668733497333b7b2ac2052fe5949985f8f51..a4f5e4999c3fb549c635a5b1295a1323bc3a9fe7 100644 (file)
@@ -9,10 +9,14 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.mapping.config;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectNameAttributeReadingStrategy;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
@@ -22,9 +26,9 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.annotation.Nullable;
 import javax.management.ObjectName;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -33,6 +37,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public final class Services {
+
     private static final Logger logger = LoggerFactory.getLogger(Services.class);
 
     private static final String PROVIDER_KEY = "provider";
@@ -42,58 +47,33 @@ public final class Services {
 
     private long suffix = 1;
 
-    private final Map<ServiceInstance, String> instanceToRef = Maps.newHashMap();
     private final Map<String /*Namespace*/, Map<String/* ServiceName */, Map<String/* refName */, ServiceInstance>>> namespaceToServiceNameToRefNameToInstance = Maps
             .newHashMap();
+    private ServiceReferenceReadableRegistry configServiceRefRegistry;
 
-    public String addServiceEntry(String namespace, String serviceName, ObjectName on) {
-
-        String moduleName = on.getKeyProperty("moduleFactoryName");
-        String instanceName = on.getKeyProperty("instanceName");
-
-        String refName = addServiceEntry(namespace, serviceName, moduleName, instanceName);
-        logger.trace("Added service entry to tracker. Service name {}, ref name {}, module name {}, instance name {}",
-                serviceName, refName, moduleName, instanceName);
-        return refName;
+    public Services(ServiceReferenceReadableRegistry configServiceRefRegistry) {
+        this.configServiceRefRegistry = configServiceRefRegistry;
     }
 
     @VisibleForTesting
-    public String addServiceEntry(String namespace, String serviceName, String moduleName, String instanceName) {
-        ServiceInstance serviceInstance = new ServiceInstance(moduleName, instanceName);
-        serviceInstance.setServiceName(serviceName);
+    public String getNewDefaultRefName(String namespace, String serviceName, String moduleName, String instanceName) {
+        String refName;
+        refName = "ref_" + instanceName;
 
-        String refName = instanceToRef.get(serviceInstance);
+        Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
 
-        Map<String, Map<String, ServiceInstance>> serviceNameToRefNameToInstance = namespaceToServiceNameToRefNameToInstance.get(namespace);
-        if (serviceNameToRefNameToInstance == null) {
-            serviceNameToRefNameToInstance = Maps.newHashMap();
-            namespaceToServiceNameToRefNameToInstance.put(namespace, serviceNameToRefNameToInstance);
-        }
+        Map<String, String> refNameToInstance;
+        if(serviceNameToRefNameToInstance == null || serviceNameToRefNameToInstance.containsKey(serviceName) == false) {
+            refNameToInstance = Collections.emptyMap();
+        } else
+            refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
 
-        Map<String, ServiceInstance> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
-        if (refNameToInstance == null) {
-            refNameToInstance = Maps.newHashMap();
-            serviceNameToRefNameToInstance.put(serviceName, refNameToInstance);
+        final Set<String> refNamesAsSet = toSet(refNameToInstance.keySet());
+        if (refNamesAsSet.contains(refName)) {
+            refName = findAvailableRefName(refName, refNamesAsSet);
         }
 
-        if (refName != null) {
-            if (serviceNameToRefNameToInstance.get(serviceName).containsKey(moduleName) == false) {
-                refNameToInstance.put(refName, serviceInstance);
-            }
-            return refName;
-        } else {
-            refName = "ref_" + instanceName;
-
-            final Set<String> refNamesAsSet = toSet(instanceToRef.values());
-            if (refNamesAsSet.contains(refName)) {
-                refName = findAvailableRefName(refName, refNamesAsSet);
-            }
-
-            instanceToRef.put(serviceInstance, refName);
-            refNameToInstance.put(refName, serviceInstance);
-
-            return refName;
-        }
+        return refName;
     }
 
     private Set<String> toSet(Collection<String> values) {
@@ -109,15 +89,15 @@ public final class Services {
     }
 
     public ServiceInstance getByServiceAndRefName(String namespace, String serviceName, String refName) {
-        Map<String, Map<String, ServiceInstance>> serviceNameToRefNameToInstance = namespaceToServiceNameToRefNameToInstance.get(namespace);
-        Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace + " , "
-                + serviceNameToRefNameToInstance.keySet());
+        Map<String, Map<String, String>> serviceNameToRefNameToInstance = getMappedServices().get(namespace);
+
+        Preconditions.checkArgument(serviceNameToRefNameToInstance != null, "No serviceInstances mapped to " + namespace);
 
-        Map<String, ServiceInstance> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
+        Map<String, String> refNameToInstance = serviceNameToRefNameToInstance.get(serviceName);
         Preconditions.checkArgument(refNameToInstance != null, "No serviceInstances mapped to " + serviceName + " , "
                 + serviceNameToRefNameToInstance.keySet());
 
-        ServiceInstance serviceInstance = refNameToInstance.get(refName);
+        ServiceInstance serviceInstance = ServiceInstance.fromString(refNameToInstance.get(refName));
         Preconditions.checkArgument(serviceInstance != null, "No serviceInstance mapped to " + refName
                 + " under service name " + serviceName + " , " + refNameToInstance.keySet());
         return serviceInstance;
@@ -136,26 +116,61 @@ public final class Services {
 
             for (String serviceName : serviceNameToRefNameToInstance.keySet()) {
 
-                Map<String, String> innerInnerRetVal = Maps.transformValues(
-                        serviceNameToRefNameToInstance.get(serviceName), new Function<ServiceInstance, String>() {
-                            @Nullable
-                            @Override
-                            public String apply(@Nullable ServiceInstance serviceInstance) {
-                                return serviceInstance.toString();
-                            }
-                        });
+                Map<String, String> innerInnerRetVal = Maps.newHashMap();
+                for (Entry<String, ServiceInstance> refNameToSi : serviceNameToRefNameToInstance.get(serviceName).entrySet()) {
+                    innerInnerRetVal.put(refNameToSi.getKey(), refNameToSi.getValue().toString());
+                }
                 innerRetVal.put(serviceName, innerInnerRetVal);
             }
             retVal.put(namespace, innerRetVal);
         }
 
+        Map<String, Map<String, ObjectName>> serviceMapping = configServiceRefRegistry.getServiceMapping();
+        for (String serviceQName : serviceMapping.keySet())
+            for (String refName : serviceMapping.get(serviceQName).keySet()) {
+
+                ObjectName on = serviceMapping.get(serviceQName).get(refName);
+                ServiceInstance si = ServiceInstance.fromObjectName(on);
+
+                // FIXME use QName's new String constructor, after its implemented
+                Pattern p = Pattern.compile("\\(([^\\(\\?]+)\\?[^\\?\\)]*\\)([^\\)]+)");
+                Matcher matcher = p.matcher(serviceQName);
+                Preconditions.checkArgument(matcher.matches());
+                String namespace = matcher.group(1);
+                String localName = matcher.group(2);
+
+                Map<String, Map<String, String>> serviceToRefs = retVal.get(namespace);
+                if(serviceToRefs==null) {
+                    serviceToRefs = Maps.newHashMap();
+                    retVal.put(namespace, serviceToRefs);
+                }
+
+                Map<String, String> refsToSis = serviceToRefs.get(localName);
+                if(refsToSis==null) {
+                    refsToSis = Maps.newHashMap();
+                    serviceToRefs.put(localName, refsToSis);
+                }
+
+                Preconditions.checkState(refsToSis.containsKey(refName) == false,
+                        "Duplicate reference name %s for service %s:%s, now for instance %s", refName, namespace,
+                        localName, on);
+                refsToSis.put(refName, si.toString());
+            }
+
         return retVal;
     }
 
+    /**
+     *
+     */
+    public Map<String, Map<String, Map<String, ServiceInstance>>> getNamespaceToServiceNameToRefNameToInstance() {
+        return namespaceToServiceNameToRefNameToInstance;
+    }
+
     // TODO hide resolveServices, call it explicitly in fromXml
 
-    public static Services resolveServices(Map<String, Map<String, Map<String, String>>> mappedServices) {
-        Services tracker = new Services();
+    public static Services resolveServices(Map<String, Map<String, Map<String, String>>> mappedServices, ServiceReferenceReadableRegistry taClient) {
+        Services tracker = new Services(taClient);
 
         for (Entry<String, Map<String, Map<String, String>>> namespaceEntry : mappedServices.entrySet()) {
             String namespace = namespaceEntry.getKey();
@@ -179,18 +194,18 @@ public final class Services {
                     }
 
                     String refName = refEntry.getKey();
-                    Preconditions.checkState(false == refNameToInstance.containsKey(refName),
-                            "Duplicate reference name to service " + refName + " under service " + serviceName);
+
                     ServiceInstance serviceInstance = ServiceInstance.fromString(refEntry.getValue());
                     refNameToInstance.put(refName, serviceInstance);
 
-                    tracker.instanceToRef.put(serviceInstance, refEntry.getKey());
                 }
             }
         }
         return tracker;
     }
 
+    // TODO support edit strategies on services
+
     public static Map<String, Map<String, Map<String, String>>> fromXml(XmlElement xml) {
         Map<String, Map<String, Map<String, String>>> retVal = Maps.newHashMap();
 
@@ -275,6 +290,51 @@ public final class Services {
         return root;
     }
 
+    public String getRefName(String namespace, String serviceName, ObjectName on, Optional<String> expectedRefName) {
+        Optional<String> refNameOptional = getRefNameOptional(namespace, serviceName, on, expectedRefName);
+        Preconditions.checkState(refNameOptional.isPresent(), "No reference names mapped to %s, %s, %s", namespace,
+                serviceName, on);
+        return refNameOptional.get();
+    }
+
+    public Optional<String> getRefNameOptional(String namespace, String serviceName, ObjectName on,
+            Optional<String> expectedRefName) {
+        Map<String, Map<String, String>> services = getMappedServices().get(namespace);
+
+        if(services == null) return Optional.absent();
+        Map<String, String> refs = services.get(serviceName);
+
+        if(refs == null) return Optional.absent();
+        Multimap<ServiceInstance, String> reverted = revertMap(refs);
+
+        ServiceInstance serviceInstance = ServiceInstance.fromObjectName(on);
+        Collection<String> references = reverted.get(serviceInstance);
+
+        if (expectedRefName.isPresent() && references.contains(expectedRefName.get())) {
+            logger.debug("Returning expected ref name {} for {}", expectedRefName.get(), on);
+            return expectedRefName;
+        } else if (references.size() > 0) {
+            String next = references.iterator().next();
+            logger.debug("Returning random ref name {} for {}", next, on);
+            return Optional.of(next);
+        } else
+            return Optional.absent();
+    }
+
+    private Multimap<ServiceInstance, String> revertMap(Map<String, String> refs) {
+        Multimap<ServiceInstance, String> multimap = HashMultimap.create();
+
+        for (Entry<String, String> e : refs.entrySet()) {
+            multimap.put(ServiceInstance.fromString(e.getValue()), e.getKey());
+        }
+
+        return multimap;
+    }
+
+    public boolean hasRefName(String key, String value, ObjectName on) {
+        return getRefNameOptional(key, value, on, Optional.<String>absent()).isPresent();
+    }
+
     public static final class ServiceInstance {
         public ServiceInstance(String moduleName, String instanceName) {
             this.moduleName = moduleName;
@@ -372,6 +432,13 @@ public final class Services {
             return true;
         }
 
+        public ObjectName getObjectName(String transactionName) {
+            return ObjectNameUtil.createTransactionModuleON(transactionName, moduleName, instanceName);
+        }
+
+        public static ServiceInstance fromObjectName(ObjectName on) {
+            return new ServiceInstance(ObjectNameUtil.getFactoryName(on), ObjectNameUtil.getInstanceName(on));
+        }
     }
 
 }
index 64f295a4d885f784a1f2c6a0ddaea915bc19ee8e..89c782c51c86e6acda56b426e6d76a70c2bc0c30 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.runti
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
@@ -60,8 +61,8 @@ public class Runtime {
         return retVal;
     }
 
-    public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document) {
-        Services serviceTracker = new Services();
+    public Element toXml(Set<ObjectName> instancesToMap, Set<ObjectName> configBeans, Document document, ServiceReferenceReadableRegistry serviceRegistry) {
+        Services serviceTracker = new Services(serviceRegistry);
 
         Element root = document.createElement(XmlNetconfConstants.DATA_KEY);
 
@@ -72,7 +73,7 @@ public class Runtime {
 
         Map<String, Multimap<String, ObjectName>> moduleToRuntimeInstance = mapInstancesToModules(instancesToMap);
         Map<String, Map<String, Collection<ObjectName>>> moduleToConfigInstance = Config.getMappedInstances(
-                configBeans, serviceTracker, moduleConfigs);
+                configBeans, moduleConfigs);
 
         for (String localNamespace : moduleConfigs.keySet()) {
 
index d8ea7d7af7ac955b339d629312d84b98a9fdf617..65df965afd1e08167c63f70ba0c56159a085d2db 100644 (file)
@@ -8,38 +8,38 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import java.util.Map;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Map;
+
 public abstract class AbstractEditConfigStrategy implements EditConfigStrategy {
 
     private static final Logger logger = LoggerFactory.getLogger(AbstractEditConfigStrategy.class);
 
     @Override
     public void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
-            ConfigTransactionClient ta) {
+                                     ConfigTransactionClient ta, Services services) {
 
         try {
             ObjectName on = ta.lookupConfigBean(module, instance);
             logger.debug("ServiceInstance for {} {} located successfully under {}", module, instance, on);
-            executeStrategy(configuration, ta, on);
+            executeStrategy(configuration, ta, on, services);
         } catch (InstanceNotFoundException e) {
-            handleMissingInstance(configuration, ta, module, instance);
+            handleMissingInstance(configuration, ta, module, instance, services);
         }
 
     }
 
     abstract void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
-            String module, String instance);
+                                        String module, String instance, Services services);
 
     abstract void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
-            ObjectName objectName);
+                                  ObjectName objectName, Services services);
 
 }
index ffe107f8ce726953f376e98327be466f80d69437..12beaf8f8e19ff29048cb12c426c372ff047d14c 100644 (file)
@@ -8,28 +8,40 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import java.util.Map;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Map;
+
 public class DeleteEditConfigStrategy extends AbstractEditConfigStrategy {
 
     private static final Logger logger = LoggerFactory.getLogger(DeleteEditConfigStrategy.class);
 
+    private final Multimap<String, String> providedServices;
+
+    public DeleteEditConfigStrategy() {
+        this.providedServices = HashMultimap.create();
+    }
+
+    public DeleteEditConfigStrategy(Multimap<String, String> providedServices) {
+        this.providedServices = providedServices;
+    }
+
     @Override
     void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
-            String module, String instance) {
+                               String module, String instance, Services services) {
         throw new IllegalStateException("Unable to delete " + module + ":" + instance + " , ServiceInstance not found");
     }
 
     @Override
-    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, Services services) {
         try {
             ta.destroyModule(on);
             logger.debug("ServiceInstance {} deleted successfully", on);
index 1fca16433a9ac7d1e3af41c64c9167138b5afd65..1bb1d9bfba7babf8fa2dc504909e4f89b6730530 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
@@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 import java.util.HashMap;
 import java.util.Map;
@@ -61,6 +63,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     @VisibleForTesting
     Element getResponseInternal(final Document document,
             final EditConfigXmlParser.EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
+
         if (editConfigExecution.shouldTest()) {
             executeTests(configRegistryClient, editConfigExecution);
         }
@@ -91,7 +94,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     private void executeTests(ConfigRegistryClient configRegistryClient,
             EditConfigExecution editConfigExecution) throws NetconfDocumentedException {
         try {
-            test(configRegistryClient, editConfigExecution.getResolvedXmlElements(), editConfigExecution.getDefaultStrategy());
+            test(configRegistryClient, editConfigExecution, editConfigExecution.getDefaultStrategy());
         } catch (IllegalStateException | JmxAttributeValidationException | ValidationException e) {
             logger.warn("Test phase for {} failed", EditConfigXmlParser.EDIT_CONFIG, e);
             final Map<String, String> errorInfo = new HashMap<>();
@@ -103,7 +106,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     }
 
     private void test(ConfigRegistryClient configRegistryClient,
-                      Map<String, Multimap<String, ModuleElementResolved>> resolvedModules, EditStrategyType editStrategyType) {
+                      EditConfigExecution execution, EditStrategyType editStrategyType) {
         ObjectName taON = transactionProvider.getTestTransaction();
         try {
 
@@ -111,7 +114,9 @@ public class EditConfig extends AbstractConfigNetconfOperation {
             if (editStrategyType == EditStrategyType.replace) {
                 transactionProvider.wipeTestTransaction(taON);
             }
-            setOnTransaction(configRegistryClient, resolvedModules, taON);
+
+            setOnTransaction(configRegistryClient, execution.getResolvedXmlElements(), execution.getServices(), taON);
+            // TODO add service reference persistance testing here
             transactionProvider.validateTestTransaction(taON);
         } finally {
             transactionProvider.abortTestTransaction(taON);
@@ -126,11 +131,45 @@ public class EditConfig extends AbstractConfigNetconfOperation {
         if (editConfigExecution.getDefaultStrategy() == EditStrategyType.replace) {
             transactionProvider.wipeTransaction();
         }
-        setOnTransaction(configRegistryClient, editConfigExecution.getResolvedXmlElements(), taON);
+
+        setOnTransaction(configRegistryClient, editConfigExecution.getResolvedXmlElements(),
+                editConfigExecution.getServices(), taON);
+        setServicesOnTransaction(configRegistryClient, editConfigExecution.getServices(), taON);
+    }
+
+    private void setServicesOnTransaction(ConfigRegistryClient configRegistryClient, Services services,
+                ObjectName taON) {
+        ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
+
+        Map<String, Map<String, Map<String, Services.ServiceInstance>>> namespaceToServiceNameToRefNameToInstance = services
+                .getNamespaceToServiceNameToRefNameToInstance();
+
+        for (String serviceNamespace : namespaceToServiceNameToRefNameToInstance.keySet()) {
+            for (String serviceName : namespaceToServiceNameToRefNameToInstance.get(serviceNamespace).keySet()) {
+
+                String qnameOfService = getQname(ta, serviceNamespace, serviceName);
+                Map<String, Services.ServiceInstance> refNameToInstance = namespaceToServiceNameToRefNameToInstance
+                        .get(serviceNamespace).get(serviceName);
+
+                for (String refName : refNameToInstance.keySet()) {
+                    ObjectName on = refNameToInstance.get(refName).getObjectName(ta.getTransactionName());
+                    // TODO check for duplicates
+                    try {
+                        ta.saveServiceReference(qnameOfService, refName, on);
+                    } catch (InstanceNotFoundException e) {
+                        throw new IllegalStateException("Unable to save ref name " + refName + " for instance " + on, e);
+                    }
+                }
+            }
+        }
+    }
+
+    private String getQname(ConfigTransactionClient ta, String namespace, String serviceName) {
+        return ta.getServiceInterfaceName(namespace, serviceName);
     }
 
     private void setOnTransaction(ConfigRegistryClient configRegistryClient,
-            Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements, ObjectName taON) {
+                                  Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements, Services services, ObjectName taON) {
         ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
 
         for (Multimap<String, ModuleElementResolved> modulesToResolved : resolvedXmlElements.values()) {
@@ -142,7 +181,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
 
                 InstanceConfigElementResolved ice = moduleElementResolved.getInstanceConfigElementResolved();
                 EditConfigStrategy strategy = ice.getEditStrategy();
-                strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta);
+                strategy.executeConfiguration(moduleName, instanceName, ice.getConfiguration(), ta, services);
             }
         }
     }
index 6b7b622d56cb785370d1a578c8045dbba3f94338..23166e8cca5c6e0d4c6fbc955de83de8db94a6f3 100644 (file)
@@ -10,12 +10,13 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed
 
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 
 import java.util.Map;
 
 public interface EditConfigStrategy {
 
     void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
-            ConfigTransactionClient ta);
+                              ConfigTransactionClient ta, Services services);
 
 }
index 3d4e5b6d0c2b9b431ae1d73cae22ea035cb304b6..81327133b82a440c9b7599672134e7b63fd00f49 100644 (file)
@@ -12,10 +12,13 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Multimap;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -25,9 +28,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.management.ObjectName;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Map;
-import java.util.Set;
 
 public class EditConfigXmlParser {
 
@@ -47,6 +48,8 @@ public class EditConfigXmlParser {
                                                     TransactionProvider transactionProvider, ConfigRegistryClient configRegistryClient)
             throws NetconfDocumentedException {
 
+        //TODO remove transactionProvider and CfgRegistry from parameters, accept only service ref store
+
         EditStrategyType editStrategyType = EditStrategyType.getDefaultStrategy();
 
         xml.checkName(EditConfigXmlParser.EDIT_CONFIG);
@@ -92,21 +95,14 @@ public class EditConfigXmlParser {
             logger.trace("Setting merge strategy to {}", mergeStrategyString);
             editStrategyType = EditStrategyType.valueOf(mergeStrategyString);
         }
-        Set<ObjectName> instancesForFillingServiceRefMapping = Collections.emptySet();
-        if (editStrategyType == EditStrategyType.merge) {
-            instancesForFillingServiceRefMapping = Datastore.getInstanceQueryStrategy(targetDatastore, transactionProvider)
-                    .queryInstances(configRegistryClient);
-            logger.trace("Pre-filling services from following instances: {}", instancesForFillingServiceRefMapping);
-        }
 
         XmlElement configElement = xml.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.CONFIG_KEY);
 
-        return new EditConfigXmlParser.EditConfigExecution(xml, cfgMapping, configElement, testOption,
-                instancesForFillingServiceRefMapping, editStrategyType);
-    }
+        ObjectName taON = transactionProvider.getOrCreateTransaction();
+        ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(taON);
 
-    private void removeMountpointsFromConfig(XmlElement configElement, XmlElement mountpointsElement) {
-        configElement.getDomElement().removeChild(mountpointsElement.getDomElement());
+        return new EditConfigXmlParser.EditConfigExecution(cfgMapping, configElement, testOption,
+                ta, editStrategyType);
     }
 
     @VisibleForTesting
@@ -135,15 +131,16 @@ public class EditConfigXmlParser {
 
     @VisibleForTesting
     static class EditConfigExecution {
-        private final XmlElement editConfigXml;
+
         private final Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements;
         private final TestOption testOption;
         private final EditStrategyType defaultEditStrategyType;
+        private final Services services;
 
-        EditConfigExecution(XmlElement xml, Config configResolver, XmlElement configElement, TestOption testOption, Set<ObjectName> instancesForFillingServiceRefMapping,
-                            EditStrategyType defaultStrategy) {
-            this.editConfigXml = xml;
-            this.resolvedXmlElements = configResolver.fromXml(configElement, instancesForFillingServiceRefMapping, defaultStrategy);
+        EditConfigExecution(Config configResolver, XmlElement configElement, TestOption testOption, ServiceReferenceReadableRegistry ta, EditStrategyType defaultStrategy) {
+            Config.ConfigElementResolved configElementResolved = configResolver.fromXml(configElement, defaultStrategy, ta);
+            this.resolvedXmlElements = configElementResolved.getResolvedModules();
+            this.services = configElementResolved.getServices();
             this.testOption = testOption;
             this.defaultEditStrategyType = defaultStrategy;
         }
@@ -163,5 +160,9 @@ public class EditConfigXmlParser {
         EditStrategyType getDefaultStrategy() {
             return defaultEditStrategyType;
         }
+
+        Services getServices() {
+            return services;
+        }
     }
 }
index cb03342a1e1febf8d883b1a47ac271ade2c96637..676467553bb61c5c46e380c8b8e33331778ea141 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
+import com.google.common.collect.Multimap;
+
 import java.util.EnumSet;
 import java.util.Set;
 
@@ -40,14 +42,14 @@ public enum EditStrategyType {
         }
     }
 
-    public EditConfigStrategy getFittingStrategy() {
+    public EditConfigStrategy getFittingStrategy(Multimap<String, String> providedServices) {
         switch (this) {
         case merge:
-            return new MergeEditConfigStrategy();
+            return new MergeEditConfigStrategy(providedServices);
         case replace:
-            return new ReplaceEditConfigStrategy();
+            return new ReplaceEditConfigStrategy(providedServices);
         case delete:
-            return new DeleteEditConfigStrategy();
+            return new DeleteEditConfigStrategy(providedServices);
         case remove:
             return new RemoveEditConfigStrategy();
         case none:
index 2a4a784a8a7bea85a4bcfdc3ee10836d00b5aa1d..06befb0565067592b58465782d66caa74a568100 100644 (file)
@@ -8,37 +8,67 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.management.Attribute;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.Attribute;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Map.Entry;
+
 public class MergeEditConfigStrategy extends AbstractEditConfigStrategy {
 
     private static final Logger logger = LoggerFactory.getLogger(MergeEditConfigStrategy.class);
+    private final Multimap<String, String> providedServices;
+
+    public MergeEditConfigStrategy() {
+        this.providedServices = HashMultimap.create();
+    }
+
+    public MergeEditConfigStrategy(Multimap<String, String> providedServices) {
+        this.providedServices = providedServices;
+    }
 
     @Override
     void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
-            String module, String instance) {
-        ObjectName on;
+                               String module, String instance, Services services) {
+        ObjectName on = null;
         try {
             on = ta.createModule(module, instance);
             logger.info("New instance for {} {} created under name {}", module, instance, on);
-            executeStrategy(configuration, ta, on);
+            addRefNames(services, providedServices, module, instance, ta, on);
+            executeStrategy(configuration, ta, on, services);
         } catch (InstanceAlreadyExistsException e1) {
             throw new IllegalStateException("Unable to create instance for " + module + " : " + instance);
+        } catch (InstanceNotFoundException e) {
+            throw new IllegalStateException("Unable to save default ref name for instance " + on, e);
+        }
+    }
+
+    private void addRefNames(Services services, Multimap<String, String> providedServices, String module,
+            String instance, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
+        for (Entry<String, String> namespaceToService : providedServices.entries()) {
+
+            if(services.hasRefName(namespaceToService.getKey(),
+                    namespaceToService.getValue(), on))
+                continue;
+
+            String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
+                    module, instance);
+            ta.saveServiceReference(
+                    ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on);
         }
     }
 
     @Override
-    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, Services services) {
         for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
             try {
                 AttributeConfigElement ace = configAttributeEntry.getValue();
index db11ce381eb82db6076189fa092adcffb97ff998..8347c6b88e23325fa579527a5f30785a99216b7d 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Map;
 
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -21,7 +22,7 @@ public class NoneEditConfigStrategy implements EditConfigStrategy {
 
     @Override
     public void executeConfiguration(String module, String instance, Map<String, AttributeConfigElement> configuration,
-            ConfigTransactionClient ta) {
+                                     ConfigTransactionClient ta, Services services) {
         logger.debug("Skipping configuration element for {}:{}", module, instance);
     }
 
index 76ca09433adc8b9b4f98d3508eb586aa16c79b48..64f082da40773b4a6dab473bed7e45722847ffca 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ed
 
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -21,7 +22,7 @@ public class RemoveEditConfigStrategy extends DeleteEditConfigStrategy {
 
     @Override
     void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
-            String module, String instance) {
+                               String module, String instance, Services services) {
         logger.warn("Unable to delete {}:{}, ServiceInstance not found", module, instance);
     }
 }
index 0091d6cc84ca7a42ed13d08259685dd127fa4d56..43d852e76a32f3b35a8bee016b6ca4ab4f8c6d04 100644 (file)
@@ -8,37 +8,68 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.management.Attribute;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.Attribute;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import java.util.Map;
+import java.util.Map.Entry;
+
 public class ReplaceEditConfigStrategy extends AbstractEditConfigStrategy {
 
     private static final Logger logger = LoggerFactory.getLogger(ReplaceEditConfigStrategy.class);
 
+    private final Multimap<String, String> providedServices;
+
+    public ReplaceEditConfigStrategy() {
+        this.providedServices = HashMultimap.create();
+    }
+
+    public ReplaceEditConfigStrategy(Multimap<String, String> providedServices) {
+        this.providedServices = providedServices;
+    }
+
     @Override
     void handleMissingInstance(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta,
-            String module, String instance) {
+                               String module, String instance, Services services) {
+        ObjectName on = null;
         try {
-            ObjectName on = ta.createModule(module, instance);
+            on = ta.createModule(module, instance);
             logger.debug("New instance for {} {} created under name {}", module, instance, on);
-            executeStrategy(configuration, ta, on);
+            addRefNames(services, providedServices, module, instance, ta, on);
+            executeStrategy(configuration, ta, on, services);
         } catch (InstanceAlreadyExistsException e) {
             logger.warn("Error creating instance {}:{}, replace failed", module, instance, e);
             throw new IllegalStateException("Unable to create new instance for " + module + " : " + instance, e);
+        } catch (InstanceNotFoundException e) {
+            throw new IllegalStateException("Unable to save default ref name for instance " + on, e);
         }
     }
 
+    private void addRefNames(Services services, Multimap<String, String> providedServices, String module,
+                             String instance, ConfigTransactionClient ta, ObjectName on) throws InstanceNotFoundException {
+        for (Entry<String, String> namespaceToService : providedServices.entries()) {
+
+            if(services.hasRefName(namespaceToService.getKey(),
+                    namespaceToService.getValue(), on))
+                continue;
+
+            String refName = services.getNewDefaultRefName(namespaceToService.getKey(), namespaceToService.getValue(),
+                    module, instance);
+            ta.saveServiceReference(
+                    ta.getServiceInterfaceName(namespaceToService.getKey(), namespaceToService.getValue()), refName, on);
+        }
+    }
     @Override
-    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on) {
+    void executeStrategy(Map<String, AttributeConfigElement> configuration, ConfigTransactionClient ta, ObjectName on, Services services) {
         for (Entry<String, AttributeConfigElement> configAttributeEntry : configuration.entrySet()) {
             try {
                 AttributeConfigElement ace = configAttributeEntry.getValue();
index 7ee13aeb589c713351f760464f19a4aff48647d3..efe4f7dde9b483bd488e753a90cee2a335b4de05 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ge
 
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry;
@@ -25,6 +26,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.runtim
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.GetConfig;
+import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.slf4j.Logger;
@@ -42,11 +44,13 @@ public class Get extends AbstractConfigNetconfOperation {
 
     private final YangStoreSnapshot yangStoreSnapshot;
     private static final Logger logger = LoggerFactory.getLogger(Get.class);
+    private final TransactionProvider transactionProvider;
 
     public Get(YangStoreSnapshot yangStoreSnapshot, ConfigRegistryClient configRegistryClient,
-            String netconfSessionIdForReporting) {
+               String netconfSessionIdForReporting, TransactionProvider transactionProvider) {
         super(configRegistryClient, netconfSessionIdForReporting);
         this.yangStoreSnapshot = yangStoreSnapshot;
+        this.transactionProvider = transactionProvider;
     }
 
     private Map<String, Map<String, ModuleRuntime>> createModuleRuntimes(ConfigRegistryClient configRegistryClient,
@@ -144,7 +148,9 @@ public class Get extends AbstractConfigNetconfOperation {
 
         final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs);
 
-        final Element element = runtime.toXml(runtimeBeans, configBeans, document);
+        ObjectName txOn = transactionProvider.getOrCreateTransaction();
+        ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(txOn);
+        final Element element = runtime.toXml(runtimeBeans, configBeans, document, ta);
 
         logger.info("{} operation successful", XmlNetconfConstants.GET);
 
index f2dfc7079c869d5f8db32db4550e677bdca8a19f..d75cfd5d6f049d9d586ac856fa0ccd7b70b3c00c 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.operations.ge
 import com.google.common.base.Optional;
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
+import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
@@ -20,6 +21,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorT
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.Datastore;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
@@ -83,7 +85,13 @@ public class GetConfig extends AbstractConfigNetconfOperation {
 
         final Config configMapping = new Config(transform(configRegistryClient,
                 yangStoreSnapshot.getModuleMXBeanEntryMap()));
-        dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement);
+
+
+        ObjectName on = transactionProvider.getOrCreateTransaction();
+        ConfigTransactionClient ta = configRegistryClient.getConfigTransactionClient(on);
+
+        Services serviceTracker = new Services(ta);
+        dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement, serviceTracker);
 
         logger.info("{} operation successful", GET_CONFIG);
 
index ec1915d6fc31aaab6d55aed10ecc95e4d9177613..77c58501cd42942e8bb55793d18408f6a31c3441 100644 (file)
@@ -56,7 +56,7 @@ final class NetconfOperationProvider {
         ops.add(new EditConfig(yangStoreSnapshot, transactionProvider, configRegistryClient,
                 netconfSessionIdForReporting));
         ops.add(new Commit(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
-        ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
+        ops.add(new Get(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting, transactionProvider));
         ops.add(new DiscardChanges(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
         ops.add(new Validate(transactionProvider, configRegistryClient, netconfSessionIdForReporting));
         ops.add(new RuntimeRpc(yangStoreSnapshot, configRegistryClient, netconfSessionIdForReporting));
index b8113a090313d270c4b1a391777d0d6e2e7d759e..0fa005e04a7930df7b1e85fc3aa933da4db98ac4 100644 (file)
@@ -137,13 +137,14 @@ public class TransactionProvider implements AutoCloseable {
     }
 
     /**
-     * Wiping means removing all module instances keeping the transaction open.
+     * Wiping means removing all module instances keeping the transaction open + service references.
      */
     synchronized void wipeInternal(ObjectName taON, boolean isTest, String moduleName) {
         ConfigTransactionClient transactionClient = configRegistryClient.getConfigTransactionClient(taON);
 
         Set<ObjectName> lookupConfigBeans = moduleName == null ? transactionClient.lookupConfigBeans()
                 : transactionClient.lookupConfigBeans(moduleName);
+        int i = lookupConfigBeans.size();
         for (ObjectName instance : lookupConfigBeans) {
             try {
                 transactionClient.destroyModule(instance);
@@ -156,7 +157,10 @@ public class TransactionProvider implements AutoCloseable {
                 throw new IllegalStateException("Unable to clean configuration in transactiom " + taON, e);
             }
         }
-        logger.debug("Transaction {} wiped clean", taON);
+        logger.debug("Transaction {} wiped clean of {} config beans", taON, i);
+
+        transactionClient.removeAllServiceReferences();
+        logger.debug("Transaction {} wiped clean of all service references", taON);
     }
 
     public void wipeTransaction() {
index f8916ecac2244943b55abe0dd036e0e52204f3f3..ccb793149c4d21162ac11e3495981e4de1898faa 100644 (file)
@@ -12,12 +12,15 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.matchers.JUnitMatchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
@@ -55,15 +58,18 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
 import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 import javax.xml.parsers.ParserConfigurationException;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigInteger;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -82,7 +88,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
 public class NetconfMappingTest extends AbstractConfigTest {
     private static final Logger logger = LoggerFactory.getLogger(NetconfMappingTest.class);
 
-    private static final String INSTANCE_NAME = "test1";
+    private static final String INSTANCE_NAME = "instance-from-code";
     private static final String NETCONF_SESSION_ID = "foo";
     private NetconfTestImplModuleFactory factory;
     private DepTestImplModuleFactory factory2;
@@ -105,24 +111,99 @@ public class NetconfMappingTest extends AbstractConfigTest {
         transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
     }
 
-    private ObjectName createModule(final String instanceName) throws InstanceAlreadyExistsException {
+    private ObjectName createModule(final String instanceName) throws InstanceAlreadyExistsException, InstanceNotFoundException, URISyntaxException {
         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
 
         final ObjectName on = transaction.createModule(this.factory.getImplementationName(), instanceName);
         final NetconfTestImplModuleMXBean mxBean = transaction.newMXBeanProxy(on, NetconfTestImplModuleMXBean.class);
-        setModule(mxBean, transaction);
+        setModule(mxBean, transaction, instanceName + "_dep");
 
+        int i = 1;
+        for (Class<? extends AbstractServiceInterface> sInterface : factory.getImplementedServiceIntefaces()) {
+            ServiceInterfaceAnnotation annotation = sInterface.getAnnotation(ServiceInterfaceAnnotation.class);
+            transaction.saveServiceReference(
+                    transaction.getServiceInterfaceName(annotation.namespace(), annotation.localName()), "ref_from_code_to_" + instanceName + "_" + i++,
+                    on);
+
+        }
         transaction.commit();
         return on;
     }
 
+    @Test
+    public void testServicePersistance() throws Exception {
+        createModule(INSTANCE_NAME);
+
+        edit("netconfMessages/editConfig.xml");
+        Element config = getConfigCandidate();
+        assertCorrectServiceNames(config, 6, "ref_test2", "user_to_instance_from_code", "ref_dep_user",
+                "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
+                "ref_from_code_to_instance-from-code_1");
+
+        edit("netconfMessages/editConfig_addServiceName.xml");
+         config = getConfigCandidate();
+        assertCorrectServiceNames(config, 7, "ref_test2", "user_to_instance_from_code", "ref_dep_user",
+                "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
+                "ref_from_code_to_instance-from-code_1", "ref_dep_user_another");
+
+        commit();
+        config = getConfigRunning();
+        assertCorrectRefNamesForDependencies(config);
+        assertCorrectServiceNames(config, 7, "ref_test2", "user_to_instance_from_code", "ref_dep_user",
+                "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
+                "ref_from_code_to_instance-from-code_1", "ref_dep_user_another");
+
+        edit("netconfMessages/editConfig_replace_default.xml");
+        config = getConfigCandidate();
+        assertCorrectServiceNames(config, 2, "ref_dep", "ref_dep2");
+
+        edit("netconfMessages/editConfig_remove.xml");
+        config = getConfigCandidate();
+        assertCorrectServiceNames(config, 0);
+
+        commit();
+        config = getConfigCandidate();
+        assertCorrectServiceNames(config, 0);
+
+    }
+
+    private void assertCorrectRefNamesForDependencies(Element config) {
+        NodeList modulesList = config.getElementsByTagName("modules");
+        assertEquals(1, modulesList.getLength());
+
+        Element modules = (Element) modulesList.item(0);
+
+        String trimmedModules = XmlUtil.toString(modules).replaceAll("\\s", "");
+        int defaultRefNameCount = StringUtils.countMatches(trimmedModules, "ref_dep2");
+        int userRefNameCount = StringUtils.countMatches(trimmedModules, "ref_dep_user_two");
+
+        assertEquals(0, defaultRefNameCount);
+        assertEquals(2, userRefNameCount);
+    }
+
+    private void assertCorrectServiceNames(Element configCandidate, int servicesSize, String... refNames) {
+        NodeList elements = configCandidate.getElementsByTagName("provider");
+        assertEquals(servicesSize, elements.getLength());
+
+        NodeList servicesList = configCandidate.getElementsByTagName("services");
+        assertEquals(1, servicesList.getLength());
+
+        Element services = (Element) servicesList.item(0);
+        String trimmedServices = XmlUtil.toString(services).replaceAll("\\s", "");
+
+        for (String s : refNames) {
+            assertThat(trimmedServices, JUnitMatchers.containsString(s));
+        }
+    }
+
     @Test
     public void testConfigNetconf() throws Exception {
 
         createModule(INSTANCE_NAME);
 
         edit("netconfMessages/editConfig.xml");
-        checkBinaryLeafEdited(getConfigCandidate());
+        Element configCandidate = getConfigCandidate();
+        checkBinaryLeafEdited(configCandidate);
 
 
         // default-operation:none, should not affect binary leaf
@@ -205,6 +286,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
         return executeOp(getConfigOp, "netconfMessages/getConfig.xml");
     }
 
+    @Ignore("second edit message corrupted")
     @Test(expected = NetconfDocumentedException.class)
     public void testConfigNetconfReplaceDefaultEx() throws Exception {
 
@@ -394,7 +476,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         for (XmlElement moduleElement : modulesElement.getChildElements("module")) {
             String name = moduleElement.getOnlyChildElement("name").getTextContent();
-            if(name.equals("test1")) {
+            if(name.equals(INSTANCE_NAME)) {
                 XmlElement enumAttr = moduleElement.getOnlyChildElement(enumName);
                 assertEquals(enumContent, enumAttr.getTextContent());
 
@@ -424,7 +506,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
             }
         }
 
-        assertEquals("configAttributeType", configAttributeType.getTextContent());
+        // TODO verify if should be default value
+        assertEquals("default-string", configAttributeType.getTextContent());
     }
 
     private Map<String, Map<String, ModuleMXBeanEntry>> getMbes() throws Exception {
@@ -480,7 +563,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
     }
 
     private Element get() throws NetconfDocumentedException, ParserConfigurationException, SAXException, IOException {
-        Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID);
+        Get getOp = new Get(yangStoreSnapshot, configRegistryClient, NETCONF_SESSION_ID, transactionProvider);
         return executeOp(getOp, "netconfMessages/get.xml");
     }
 
@@ -516,8 +599,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
         return Lists.newArrayList(yangDependencies);
     }
 
-    private void setModule(final NetconfTestImplModuleMXBean mxBean, final ConfigTransactionJMXClient transaction)
-            throws InstanceAlreadyExistsException {
+    private void setModule(final NetconfTestImplModuleMXBean mxBean, final ConfigTransactionJMXClient transaction, String depName)
+            throws InstanceAlreadyExistsException, InstanceNotFoundException {
         mxBean.setSimpleInt((long) 44);
         mxBean.setBinaryLeaf(new byte[] { 8, 7, 9 });
         final DtoD dtob = getDtoD();
@@ -547,7 +630,15 @@ public class NetconfMappingTest extends AbstractConfigTest {
         mxBean.setComplexList(Lists.<ComplexList> newArrayList());
         mxBean.setSimpleList(Lists.<Integer> newArrayList());
 
-        final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), "dep");
+        final ObjectName testingDepOn = transaction.createModule(this.factory2.getImplementationName(), depName);
+        int i = 1;
+        for (Class<? extends AbstractServiceInterface> sInterface : factory2.getImplementedServiceIntefaces()) {
+            ServiceInterfaceAnnotation annotation = sInterface.getAnnotation(ServiceInterfaceAnnotation.class);
+            transaction.saveServiceReference(
+                    transaction.getServiceInterfaceName(annotation.namespace(), annotation.localName()), "ref_from_code_to_" + depName + "_" + i++,
+                    testingDepOn);
+
+        }
         mxBean.setTestingDep(testingDepOn);
     }
 
index 425ecf6d02628962de3b8268d21b119c72370bf2..d5ba976ccfd1feabbf5ec97412b09e9f0ce1f8f9 100644 (file)
@@ -13,7 +13,6 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services.ServiceInstance;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 
 public class ServiceTrackerTest {
 
@@ -28,44 +27,4 @@ public class ServiceTrackerTest {
         assertEquals(serviceInstance, serviceInstance2);
     }
 
-    @Test
-    public void testOneInstanceMultipleServices() {
-        Services services = new Services();
-        services.addServiceEntry("nm", "s1", "module", "instance");
-        assertEquals(1, services.getMappedServices().size());
-
-        services.addServiceEntry("nm2", "s2", "module", "instance");
-        assertEquals(2, services.getMappedServices().size());
-    }
-
-    @Test
-    public void testMultipleInstancesOneName() throws Exception {
-        Services services = new Services();
-        services.addServiceEntry("nm", "s1", "module", "instance");
-        assertEquals(1, services.getMappedServices().size());
-
-        services.addServiceEntry("nm", "s1", "module2", "instance");
-        assertEquals(1, services.getMappedServices().size());
-        assertEquals(2, services.getMappedServices().get("nm").get("s1").size());
-        assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance"));
-        assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance_1"));
-    }
-
-    @Test
-    public void testMultipleInstancesOneName2() throws Exception {
-        Services services = new Services();
-        services.addServiceEntry("nm", "s1", "module", "instance_1");
-
-        services.addServiceEntry("nm2", "s2", "module2", "instance");
-        services.addServiceEntry("nm2", "s2", "module3", "instance");
-        services.addServiceEntry("nm", "s1", "module3", "instance");
-
-        assertEquals(2, services.getMappedServices().get("nm").get("s1").size());
-        assertEquals(2, services.getMappedServices().get("nm2").get("s2").size());
-        assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance_2"));
-        assertTrue(services.getMappedServices().get("nm").get("s1").containsKey("ref_instance_1"));
-        assertTrue(services.getMappedServices().get("nm2").get("s2").containsKey("ref_instance"));
-        assertTrue(services.getMappedServices().get("nm2").get("s2").containsKey("ref_instance_2"));
-    }
-
 }
index 1b8e24702aa32300a600518704250b02bdd480c1..6e7a225f38452250ca4803c17ac56a2d2999822f 100644 (file)
@@ -16,24 +16,23 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.AttributeConfigElement;
-import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfigElementResolved;
 import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleElementResolved;
+import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Services;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.ValidateTest;
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfigXmlParser.EditConfigExecution;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
-import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 
 import javax.management.ObjectName;
 import java.util.Collections;
 import java.util.Map;
-import java.util.Set;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyMap;
@@ -82,18 +81,11 @@ public class EditConfigTest {
         EditConfig edit = new EditConfig(yangStoreSnapshot, provider, configRegistry,
                 ValidateTest.NETCONF_SESSION_ID_FOR_REPORTING);
         EditConfigStrategy editStrat = mock(EditConfigStrategy.class);
-        doNothing().when(editStrat).executeConfiguration(anyString(), anyString(), anyMap(),
-                any(ConfigTransactionClient.class));
-        Map<String, Multimap<String, ModuleElementResolved>> resolvedXmlElements = getMapping(editStrat);
 
-        Config cfg = mock(Config.class);
-        XmlElement xmlElement = mock(XmlElement.class);
-        Set<ObjectName> instancesForFillingServiceRefMapping = Collections.emptySet();
-        EditStrategyType defaultStrategy = EditStrategyType.getDefaultStrategy();
-        doReturn(resolvedXmlElements).when(cfg).fromXml(xmlElement, instancesForFillingServiceRefMapping, defaultStrategy);
+        doNothing().when(editStrat).executeConfiguration(anyString(), anyString(), anyMap(),
+                any(ConfigTransactionClient.class), any(Services.class));
 
-        EditConfigExecution editConfigExecution = new EditConfigExecution(null, cfg, xmlElement,
-                EditConfigXmlParser.TestOption.testThenSet, instancesForFillingServiceRefMapping, defaultStrategy);
+        EditConfigExecution editConfigExecution = mockExecution(editStrat);
 
         edit.getResponseInternal(XmlUtil.newDocument(), editConfigExecution);
 
@@ -105,7 +97,31 @@ public class EditConfigTest {
 
         // For every instance execute strat
         verify(editStrat, times(2/* Test */+ 2/* Set */)).executeConfiguration(anyString(), anyString(), anyMap(),
-                any(ConfigTransactionClient.class));
+                any(ConfigTransactionClient.class), any(Services.class));
+    }
+
+    private EditConfigExecution mockExecution(EditConfigStrategy editStrat) {
+        EditConfigExecution mock = mock(EditConfigExecution.class);
+        doReturn(getMapping(editStrat)).when(mock).getResolvedXmlElements();
+        doReturn(EditStrategyType.merge).when(mock).getDefaultStrategy();
+        doReturn(true).when(mock).shouldSet();
+        doReturn(true).when(mock).shouldTest();
+        doReturn(mockServices()).when(mock).getServices();
+        return mock;
+    }
+
+    private static ServiceReferenceReadableRegistry mockServiceRegistry() {
+        ServiceReferenceReadableRegistry mock = mock(ServiceReferenceReadableRegistry.class);
+        doReturn(
+                Collections.emptyMap())
+                .when(mock).getServiceMapping();
+        doReturn("mockedServiceReg").when(mock).toString();
+
+        return mock;
+    }
+
+    static Services mockServices() {
+        return new Services(mockServiceRegistry());
     }
 
     private Map<String, Multimap<String, ModuleElementResolved>> getMapping(EditConfigStrategy editStrat) {
index 704da6dc0d8d0819923ed67f973c01e3fa3ef045..78a2043e202413786f1000954c10289ce5395696 100644 (file)
@@ -48,7 +48,7 @@ public class ReplaceEditConfigStrategyTest {
 
         doReturn(Sets.newHashSet(mockON(), mockON())).when(ta).lookupConfigBeans();
 
-        strat.executeConfiguration("m1", "i1", map, ta);
+        strat.executeConfiguration("m1", "i1", map, ta, EditConfigTest.mockServices());
 
         verify(ta).lookupConfigBean(anyString(), anyString());
         verify(ta).setAttribute(any(ObjectName.class), anyString(), any(Attribute.class));
index 044346e2c5a06e2576b7f687975085dc1e2d60f1..89c27032851b0b63eb9141a87f8768518688cc66 100644 (file)
@@ -169,7 +169,7 @@ public class ConfigPusher {
         NetconfMessage message = createEditConfigMessage(xmlToBePersisted, "/netconfOp/editConfig.xml");
 
         // sending message to netconf
-        NetconfMessage responseMessage = netconfClient.sendMessage(message, NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
+        NetconfMessage responseMessage = getResponse(message, netconfClient);
 
         XmlElement element = XmlElement.fromDomDocument(responseMessage.getDocument());
         Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
@@ -178,7 +178,7 @@ public class ConfigPusher {
         Util.checkIsOk(element, responseMessage);
         response.append(XmlUtil.toString(responseMessage.getDocument()));
         response.append("}");
-        responseMessage = netconfClient.sendMessage(getNetconfMessageFromResource("/netconfOp/commit.xml"), NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
+        responseMessage = getResponse(getNetconfMessageFromResource("/netconfOp/commit.xml"), netconfClient);
 
         element = XmlElement.fromDomDocument(responseMessage.getDocument());
         Preconditions.checkState(element.getName().equals(XmlNetconfConstants.RPC_REPLY_KEY));
@@ -192,6 +192,15 @@ public class ConfigPusher {
         logger.trace("Detailed message {}", response);
     }
 
+    private static NetconfMessage getResponse(NetconfMessage request, NetconfClient netconfClient) {
+        try {
+            return netconfClient.sendMessage(request, NETCONF_SEND_ATTEMPTS, NETCONF_SEND_ATTEMPT_MS_DELAY);
+        } catch(RuntimeException e) {
+            logger.error("Error while sending message {} to {}", request, netconfClient);
+            throw e;
+        }
+    }
+
     private static NetconfMessage createEditConfigMessage(Element dataElement, String editConfigResourcename) {
         try (InputStream stream = ConfigPersisterNotificationHandler.class.getResourceAsStream(editConfigResourcename)) {
             Preconditions.checkNotNull(stream, "Unable to load resource " + editConfigResourcename);
index 95f526b2ecb535787570fd60fe97e96094421420..2ce779a1f54e9ce4f68b9c7f1db478d9de4e0201 100644 (file)
@@ -88,6 +88,7 @@ public class NetconfClient implements Closeable {
     }
 
     public NetconfMessage sendMessage(NetconfMessage message, int attempts, int attemptMsDelay) {
+        long startTime = System.currentTimeMillis();
         Preconditions.checkState(clientSession.isUp(), "Session was not up yet");
         clientSession.sendMessage(message);
         try {
@@ -96,6 +97,9 @@ public class NetconfClient implements Closeable {
             throw new RuntimeException(this + " Cannot read message from " + address, e);
         } catch (IllegalStateException e) {
             throw new IllegalStateException(this + " Cannot read message from " + address, e);
+        } finally {
+            long diffMillis = System.currentTimeMillis() - startTime;
+            logger.debug("Total time spent waiting for response {}", diffMillis);
         }
     }
 
index 94b73f4b100754e17918b9d5d75bed8542130f46..35cf2c6a1423e090a3205376a0c2f953c0fd4b48 100644 (file)
@@ -11,7 +11,7 @@
             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
 
                 <module>
-                    <name>dep</name>
+                    <name>instance-from-code_dep</name>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         test-impl:impl-dep
                     </type>
@@ -29,7 +29,7 @@
                         test-impl:impl-netconf
                     </type>
 
-                    <name>test1</name>
+                    <name>instance-from-code</name>
 
                     <sleep-factor>
                         2.58
                     </peers>
                     <testing-dep>
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
+                        <name>ref_dep_user</name>
                     </testing-dep>
 
                     <testing-deps>
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
+                        <name>ref_dep_user</name>
                     </testing-deps>
                     <testing-deps>
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep_2</name>
+                        <name>ref_dep_user_two</name>
                     </testing-deps>
                 </module>
 
 
                     <testing-dep>
                         <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep_2</name>
+                        <name>ref_dep_user_two</name>
                     </testing-dep>
                 </module>
             </modules>
                 <service>
                     <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
                     <instance>
-                        <name>ref_dep</name>
-                        <provider>/modules/module[type='impl-dep'][name='dep']
+                        <name>ref_dep_user</name>
+                        <provider>/modules/module[type='impl-dep'][name='instance-from-code_dep']
                         </provider>
                     </instance>
                     <instance>
-                        <name>ref_dep_2</name>
+                        <name>ref_dep_user_two</name>
                         <provider>/config/modules/module[name='impl-dep']/instance[name='dep2']
                         </provider>
                     </instance>
                     <instance>
-                        <name>ref_test1</name>
+                        <name>user_to_instance_from_code</name>
                         <provider>
-                            /modules/module[type='impl-netconf'][name='test1']
+                            /modules/module[type='impl-netconf'][name='instance-from-code']
                         </provider>
                     </instance>
                 </service>
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_addServiceName.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_addServiceName.xml
new file mode 100644 (file)
index 0000000..30be98e
--- /dev/null
@@ -0,0 +1,34 @@
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <edit-config>
+        <target>
+            <candidate/>
+        </target>
+        <test-option>
+            set
+        </test-option>
+        <default-operation>merge</default-operation>
+        <config>
+            <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+                <module>
+                    <name>instance-from-code_dep</name>
+                    <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        test-impl:impl-dep
+                    </type>
+                </module>
+
+            </modules>
+
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <service>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
+                    <instance>
+                        <name>ref_dep_user_another</name>
+                        <provider>/modules/module[type='impl-dep'][name='instance-from-code_dep']
+                        </provider>
+                    </instance>
+                </service>
+            </services>
+        </config>
+    </edit-config>
+</rpc>
index ad7c84f3c96e46d799923532c70939b7c2a0073a..25976707d4eb1295da0b1d802f218a34426dfedb 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8" ?>
 <rpc message-id="6"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
                     </name-prefix>
                 </module>
             </modules>
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <service>
+                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl">prefix:threadfactory</type>
+                    <instance>
+                        <name>user_to_instance_from_code</name>
+                        <provider>
+                            /modules/module[type='threadfactory-naming'][name='threadfactory-naming-instance']</provider>
+                    </instance>
+                </service>
+            </services>
         </config>
     </edit-config>
 </rpc>
index b48730d3f71e74a86fde37131c38602d3f1169c1..a7f1c863910f4b24b421531b82ffb9cb68499452 100644 (file)
@@ -8,7 +8,7 @@
         <config>
             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
                 <module>
-                    <name>dep</name>
+                    <name>instance-from-code_dep</name>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         test-impl:impl-dep
                     </type>
@@ -21,6 +21,7 @@
                     </type>
                 </module>
 
+
                 <module>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         test-impl:impl-netconf
                         <simple-int3>456</simple-int3>
                         <core-size>44</core-size>
                     </peers>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
                 </module>
                 <module>
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         test-impl:impl-netconf
                     </type>
                     <name>test2</name>
-                    <testing-dep>
-                        <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                        <name>ref_dep</name>
-                    </testing-dep>
                 </module>
             </modules>
+
             <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-                <service>
-                    <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test">prefix:testing</type>
-                    <instance>
-                        <name>ref_dep</name>
-                        <provider>/modules/module[type='impl-dep'][name='dep']
-                        </provider>
-                    </instance>
-                    <instance>
-                        <name>ref_dep_2</name>
-                        <provider>/modules/module[type='impl-dep'][name='dep2']
-                        </provider>
-                    </instance>
-                    <instance>
-                        <name>ref_test1</name>
-                        <provider>
-                            /modules/module[type='impl-netconf'][name='test1']
-                        </provider>
-                    </instance>
-                </service>
             </services>
         </config>
     </edit-config>
index 9d06d98f1c131b2cc405b130288fb6c375851771..e07f18cb5119b3acef99c58e684614ebff2799d7 100644 (file)
@@ -6,6 +6,15 @@
         <default-operation>none</default-operation>
         <config>
             <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+                <module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+                        nc:operation="remove">
+                    <name>instance-from-code_dep</name>
+                    <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+                        test-impl:impl-dep
+                    </type>
+                </module>
+
+
                 <module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
                         nc:operation="remove">
                     <name>dep</name>
@@ -27,7 +36,7 @@
                     <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
                         test-impl:impl-netconf
                     </type>
-                    <name>test1</name>
+                    <name>instance-from-code</name>
                 </module>
 
                 <module xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
index 46b833cf68cb3f4ff41442880bfe043575faf63b..5de3de1de223592bac091e830109fdb54820fe18 100644 (file)
@@ -1,6 +1,6 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <no-arg xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-        <context-instance>/modules/module[type='impl-netconf' and name='test1']</context-instance>
+        <context-instance>/modules/module[type='impl-netconf' and name='instance-from-code']</context-instance>
         <arg1>
             testarg1
         </arg1>
index 3d5117e3bdf15bee2f2b51539dd5435db58874ec..da9afd7bf1e00677313215d81c26fae5af88113b 100644 (file)
@@ -1,7 +1,7 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <noArgInner xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /modules/module[name='test1'][type='impl-netconf']/inner-running-data-additional[key='1']
+            /modules/module[name='instance-from-code'][type='impl-netconf']/inner-running-data-additional[key='1']
         </context-instance>
     </noArgInner>
 </rpc>
index 4ba0349f9b7d32c2b4532f1c78eccd9d4e71fc99..a5b83e6db6f39a470462ebecda59a37e1de384bb 100644 (file)
@@ -2,7 +2,7 @@
     <leaf-list-output
             xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /modules/module[type='impl-netconf'][name='test1']/inner-running-data[key='0']/inner-inner-running-data[key='1']
+            /modules/module[type='impl-netconf'][name='instance-from-code']/inner-running-data[key='0']/inner-inner-running-data[key='1']
         </context-instance>
     </leaf-list-output>
 </rpc>
diff --git a/pom.xml b/pom.xml
index f7f9bc2256b35c72697d4deeaef84e70930521ec..6ece420d5ad01e252c431fd7a4ab38f2240dcd3c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
     <module>opendaylight/commons/opendaylight</module>
     <module>opendaylight/commons/parent</module>
     <module>opendaylight/commons/logback_settings</module>
+    <module>opendaylight/commons/controller-maven-plugin</module>
   </modules>
 
     <profiles>
                 <module>opendaylight/statisticsmanager/integrationtest</module>
                 <module>opendaylight/commons/integrationtest</module>
                 <module>opendaylight/containermanager/it.implementation</module>
-                <module>opendaylight/distribution/sanitytest/</module>
             </modules>
         </profile>
         <profile>