Merge "Clean up yang-test to stop modifying source files during build."
authorEd Warnicke <eaw@cisco.com>
Wed, 30 Apr 2014 11:57:49 +0000 (11:57 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 30 Apr 2014 11:57:49 +0000 (11:57 +0000)
25 files changed:
opendaylight/config/yang-jmx-generator-plugin/pom.xml
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.groovy [deleted file]
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.groovy [deleted file]
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java [new file with mode: 0644]
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.groovy [deleted file]
opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.java [new file with mode: 0644]
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractListeningStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/AbstractStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowTableStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupDescStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/GroupStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterConfigStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/MeterStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeConnectorStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/NodeStatisticsHandler.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/QueueStatsTracker.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsProvider.java
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java [new file with mode: 0644]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/authentication/AuthProvider.java
opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/netconf/ssh/osgi/NetconfSSHActivator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java

index 2d49ed7fab1bb21b595d68d35683c8d9e7d7f85a..b8831f6979ec3205e496c13ee1df15217d3d9feb 100644 (file)
 
   </dependencies>
 
-  <build>
-    <plugins>
-      <plugin>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>3.1</version>
-        <configuration>
-          <compilerId>groovy-eclipse-compiler</compilerId>
-          <verbose>false</verbose>
-        </configuration>
-        <dependencies>
-
-          <dependency>
-            <groupId>org.codehaus.groovy</groupId>
-            <artifactId>groovy-eclipse-batch</artifactId>
-            <version>2.1.8-01</version>
-          </dependency>
-          <dependency>
-            <groupId>org.codehaus.groovy</groupId>
-            <artifactId>groovy-eclipse-compiler</artifactId>
-            <version>2.8.0-01</version>
-          </dependency>
-        </dependencies>
-      </plugin>
-
-    </plugins>
-  </build>
 </project>
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.groovy b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.groovy
deleted file mode 100644 (file)
index baff88c..0000000
+++ /dev/null
@@ -1,168 +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.yangjmxgenerator.plugin.gofactory
-import com.google.common.base.Optional
-import org.opendaylight.controller.config.api.DependencyResolver
-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.api.annotations.Description
-import org.opendaylight.controller.config.spi.Module
-import org.opendaylight.controller.config.spi.ModuleFactory
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractFactoryTemplate
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.*
-import org.opendaylight.yangtools.yang.common.QName
-import org.osgi.framework.BundleContext
-
-public class AbsFactoryGeneratedObjectFactory {
-
-    public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional<String> copyright) {
-        FullyQualifiedName absFactoryFQN = new FullyQualifiedName(mbe.packageName, mbe.abstractFactoryName)
-        FullyQualifiedName moduleFQN = new FullyQualifiedName(mbe.packageName, mbe.stubModuleName)
-        Optional<String> classJavaDoc = Optional.fromNullable(mbe.getNullableDescription())
-
-        AbstractFactoryTemplate abstractFactoryTemplate = TemplateFactory.abstractFactoryTemplateFromMbe(mbe)
-        Optional<String> header = abstractFactoryTemplate.headerString;
-        List<FullyQualifiedName> providedServices = mbe.providedServices.keySet().collect {
-            FullyQualifiedName.fromString(it)
-        }
-
-
-        return toGeneratedObject(absFactoryFQN, copyright,
-                header, classJavaDoc, mbe.yangModuleQName,
-                mbe.globallyUniqueName,
-                providedServices,
-                moduleFQN,
-                abstractFactoryTemplate.fields)
-    }
-
-    public GeneratedObject toGeneratedObject(FullyQualifiedName absFactoryFQN, Optional<String> copyright,
-                                             Optional<String> header, Optional<String> classJavaDoc, QName yangModuleQName,
-                                             String globallyUniqueName,
-                                             List<FullyQualifiedName> providedServices,
-                                             FullyQualifiedName moduleFQN,
-                                             List<Field> moduleFields) {
-        JavaFileInputBuilder b = new JavaFileInputBuilder()
-        Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName)
-        b.addClassAnnotation(moduleQNameAnnotation)
-
-        b.setFqn(absFactoryFQN)
-        b.setTypeName(TypeName.absClassType)
-
-        b.setCopyright(copyright);
-        b.setHeader(header);
-        b.setClassJavaDoc(classJavaDoc);
-        b.addImplementsFQN(new FullyQualifiedName(ModuleFactory))
-        if (classJavaDoc.isPresent()) {
-            b.addClassAnnotation("@${Description.canonicalName}(value=\"${classJavaDoc.get()}\")")
-        }
-
-        b.addToBody("public static final java.lang.String NAME = \"${globallyUniqueName}\";")
-        b.addToBody("private static final java.util.Set<Class<? extends ${AbstractServiceInterface.canonicalName}>> serviceIfcs;")
-
-        b.addToBody("@Override\n public final String getImplementationName() { \n return NAME; \n}")
-
-        b.addToBody(getServiceIfcsInitialization(providedServices))
-
-        // createModule
-        b.addToBody("""
-            @Override
-            public ${Module.canonicalName} createModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${BundleContext.canonicalName} bundleContext) {
-                return instantiateModule(instanceName, dependencyResolver, bundleContext);
-            }
-            """)
-
-        b.addToBody(getCreateModule(moduleFQN, moduleFields))
-
-        b.addToBody("""
-            public ${moduleFQN} instantiateModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${moduleFQN} oldModule, ${AutoCloseable.canonicalName} oldInstance, ${BundleContext.canonicalName} bundleContext) {
-                return new ${moduleFQN}(new ${ModuleIdentifier.canonicalName}(NAME, instanceName), dependencyResolver, oldModule, oldInstance);
-            }
-            """)
-
-        b.addToBody("""
-            public ${moduleFQN} instantiateModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${BundleContext.canonicalName} bundleContext) {
-                return new ${moduleFQN}(new ${ModuleIdentifier.canonicalName}(NAME, instanceName), dependencyResolver);
-            }
-            """)
-
-        b.addToBody("""
-            public ${moduleFQN} handleChangedClass(${DynamicMBeanWithInstance.canonicalName} old) throws Exception {
-                throw new UnsupportedOperationException("Class reloading is not supported");
-            }
-            """)
-
-        b.addToBody("""
-            @Override
-            public java.util.Set<${moduleFQN}> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory, ${BundleContext.canonicalName} bundleContext) {
-                return new java.util.HashSet<${moduleFQN}>();
-            }
-            """)
-
-        return new GeneratedObjectBuilder(b.build()).toGeneratedObject()
-    }
-
-    private static String getCreateModule(FullyQualifiedName moduleFQN, List<Field> moduleFields) {
-        String result = """
-            @Override
-            public ${Module.canonicalName} createModule(String instanceName, ${DependencyResolver.canonicalName} dependencyResolver, ${DynamicMBeanWithInstance.canonicalName} old, ${BundleContext.canonicalName} bundleContext) throws Exception {
-                ${moduleFQN} oldModule = null;
-                try {
-                    oldModule = (${moduleFQN}) old.getModule();
-                } catch(Exception e) {
-                    return handleChangedClass(old);
-                }
-                ${moduleFQN} module = instantiateModule(instanceName, dependencyResolver, oldModule, old.getInstance(), bundleContext);
-            """
-        result += moduleFields.collect{"module.set${it.name}(oldModule.get${it.name}());"}.join("\n")
-        result += """
-                return module;
-            }
-            """
-        return result
-    }
-
-    private static String getServiceIfcsInitialization(List<FullyQualifiedName> providedServices) {
-        String generic = "Class<? extends ${AbstractServiceInterface.canonicalName}>"
-
-        String result = """static {
-            java.util.Set<${generic}> serviceIfcs2 = new java.util.HashSet<${generic}>();
-            """
-        result += providedServices.collect{"serviceIfcs2.add(${it}.class);"}.join("\n")
-        result += """serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2);
-            }
-            """
-
-        // add isModuleImplementingServiceInterface and getImplementedServiceIntefaces methods
-
-        result += """
-            @Override
-            public final boolean isModuleImplementingServiceInterface(Class<? extends ${AbstractServiceInterface.canonicalName}> serviceInterface) {
-                for (Class<?> ifc: serviceIfcs) {
-                    if (serviceInterface.isAssignableFrom(ifc)){
-                        return true;
-                    }
-                }
-                return false;
-            }
-
-            @Override
-            public java.util.Set<Class<? extends ${AbstractServiceInterface.canonicalName}>> getImplementedServiceIntefaces() {
-                return serviceIfcs;
-            }
-            """
-
-        return result
-    }
-
-}
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsFactoryGeneratedObjectFactory.java
new file mode 100644 (file)
index 0000000..48a6c15
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * 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.yangjmxgenerator.plugin.gofactory;
+
+import static java.lang.String.format;
+
+import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.config.api.DependencyResolver;
+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.api.annotations.Description;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractFactoryTemplate;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.BundleContext;
+
+public class AbsFactoryGeneratedObjectFactory {
+
+    public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional<String> copyright) {
+        FullyQualifiedName absFactoryFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractFactoryName());
+        FullyQualifiedName moduleFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getStubModuleName());
+        Optional<String> classJavaDoc = Optional.fromNullable(mbe.getNullableDescription());
+
+        AbstractFactoryTemplate abstractFactoryTemplate = TemplateFactory.abstractFactoryTemplateFromMbe(mbe);
+        Optional<String> header = abstractFactoryTemplate.getHeaderString();
+
+        List<FullyQualifiedName> providedServices = new ArrayList<>();
+        for(String providedService: mbe.getProvidedServices().keySet()) {
+            providedServices.add(FullyQualifiedName.fromString(providedService));
+        }
+
+        return toGeneratedObject(absFactoryFQN, copyright,
+                header, classJavaDoc, mbe.getYangModuleQName(),
+                mbe.getGloballyUniqueName(),
+                providedServices,
+                moduleFQN,
+                abstractFactoryTemplate.getFields());
+    }
+
+    public GeneratedObject toGeneratedObject(FullyQualifiedName absFactoryFQN, Optional<String> copyright,
+                                             Optional<String> header, Optional<String> classJavaDoc, QName yangModuleQName,
+                                             String globallyUniqueName,
+                                             List<FullyQualifiedName> providedServices,
+                                             FullyQualifiedName moduleFQN,
+                                             List<Field> moduleFields) {
+        JavaFileInputBuilder b = new JavaFileInputBuilder();
+        Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName);
+        b.addClassAnnotation(moduleQNameAnnotation);
+
+        b.setFqn(absFactoryFQN);
+        b.setTypeName(TypeName.absClassType);
+
+        b.setCopyright(copyright);
+        b.setHeader(header);
+        b.setClassJavaDoc(classJavaDoc);
+        b.addImplementsFQN(new FullyQualifiedName(ModuleFactory.class));
+        if (classJavaDoc.isPresent()) {
+            b.addClassAnnotation(format("@%s(value=\"%s\")", Description.class.getCanonicalName(), classJavaDoc.get()));
+        }
+
+        b.addToBody(format("public static final java.lang.String NAME = \"%s\";", globallyUniqueName));
+        b.addToBody(format("private static final java.util.Set<Class<? extends %s>> serviceIfcs;",
+                AbstractServiceInterface.class.getCanonicalName()));
+
+        b.addToBody("@Override\n public final String getImplementationName() { \n return NAME; \n}");
+
+        b.addToBody(getServiceIfcsInitialization(providedServices));
+
+        // createModule
+        b.addToBody(format("\n"+
+            "@Override\n"+
+            "public %s createModule(String instanceName, %s dependencyResolver, %s bundleContext) {\n"+
+                "return instantiateModule(instanceName, dependencyResolver, bundleContext);\n"+
+            "}\n",
+                Module.class.getCanonicalName(), DependencyResolver.class.getCanonicalName(), BundleContext.class.getCanonicalName()));
+
+        b.addToBody(getCreateModule(moduleFQN, moduleFields));
+
+        b.addToBody(format("\n"+
+            "public %s instantiateModule(String instanceName, %s dependencyResolver, %s oldModule, %s oldInstance, %s bundleContext) {\n"+
+                "return new %s(new %s(NAME, instanceName), dependencyResolver, oldModule, oldInstance);\n"+
+            "}\n",
+                moduleFQN, DependencyResolver.class.getCanonicalName(), moduleFQN, AutoCloseable.class.getCanonicalName(),
+                BundleContext.class.getCanonicalName(), moduleFQN, ModuleIdentifier.class.getCanonicalName()));
+
+        b.addToBody(format("\n"+
+            "public %s instantiateModule(String instanceName, %s dependencyResolver, %s bundleContext) {\n"+
+                "return new %s(new %s(NAME, instanceName), dependencyResolver);\n"+
+            "}\n", moduleFQN, DependencyResolver.class.getCanonicalName(), BundleContext.class.getCanonicalName(),
+                moduleFQN, ModuleIdentifier.class.getCanonicalName()
+        ));
+
+        b.addToBody(format("\n"+
+            "public %s handleChangedClass(%s old) throws Exception {\n"+
+                "throw new UnsupportedOperationException(\"Class reloading is not supported\");\n"+
+            "}\n", moduleFQN, DynamicMBeanWithInstance.class.getCanonicalName()));
+
+        b.addToBody(format("\n"+
+            "@Override\n"+
+            "public java.util.Set<%s> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory, %s bundleContext) {\n"+
+                "return new java.util.HashSet<%s>();\n"+
+            "}\n", moduleFQN, BundleContext.class.getCanonicalName(), moduleFQN));
+
+        return new GeneratedObjectBuilder(b.build()).toGeneratedObject();
+    }
+
+    private static String getCreateModule(FullyQualifiedName moduleFQN, List<Field> moduleFields) {
+        String result = "\n"+
+            "@Override\n"+
+            format("public %s createModule(String instanceName, %s dependencyResolver, %s old, %s bundleContext) throws Exception {\n",
+                                Module.class.getCanonicalName(),DependencyResolver.class.getCanonicalName(),
+                                DynamicMBeanWithInstance.class.getCanonicalName(),BundleContext.class.getCanonicalName())+
+                format("%s oldModule = null;\n",moduleFQN)+
+                "try {\n"+
+                    format("oldModule = (%s) old.getModule();\n",moduleFQN)+
+                "} catch(Exception e) {\n"+
+                    "return handleChangedClass(old);\n"+
+                "}\n"+
+            format("%s module = instantiateModule(instanceName, dependencyResolver, oldModule, old.getInstance(), bundleContext);\n", moduleFQN);
+
+        for(Field field: moduleFields) {
+            result += format("module.set%s(oldModule.get%1$s());\n", field.getName());
+        }
+
+        result += "\n"+
+                "return module;\n"+
+            "}\n";
+        return result;
+    }
+
+    private static String getServiceIfcsInitialization(List<FullyQualifiedName> providedServices) {
+        String generic = format("Class<? extends %s>", AbstractServiceInterface.class.getCanonicalName());
+
+        String result = format("static {\n"+
+            "java.util.Set<%1$s> serviceIfcs2 = new java.util.HashSet<%1$s>();\n", generic);
+
+        for(FullyQualifiedName fqn: providedServices) {
+            result += format("serviceIfcs2.add(%s.class);\n", fqn);
+        }
+        result += "serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2);\n"+
+            "}\n";
+
+        // add isModuleImplementingServiceInterface and getImplementedServiceIntefaces methods
+
+        result += format("\n"+
+            "@Override\n"+
+            "public final boolean isModuleImplementingServiceInterface(Class<? extends %1$s> serviceInterface) {\n"+
+                "for (Class<?> ifc: serviceIfcs) {\n"+
+                    "if (serviceInterface.isAssignableFrom(ifc)){\n"+
+                        "return true;\n"+
+                    "}\n"+
+                "}\n"+
+                "return false;\n"+
+            "}\n"+
+            "\n"+
+            "@Override\n"+
+            "public java.util.Set<Class<? extends %1$s>> getImplementedServiceIntefaces() {\n"+
+                "return serviceIfcs;\n"+
+            "}\n", AbstractServiceInterface.class.getCanonicalName());
+
+        return result;
+    }
+
+}
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.groovy b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.groovy
deleted file mode 100644 (file)
index 930acff..0000000
+++ /dev/null
@@ -1,400 +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.yangjmxgenerator.plugin.gofactory
-import com.google.common.base.Optional
-import org.opendaylight.controller.config.api.DependencyResolver
-import org.opendaylight.controller.config.api.ModuleIdentifier
-import org.opendaylight.controller.config.api.annotations.Description
-import org.opendaylight.controller.config.api.runtime.RootRuntimeBeanRegistrator
-import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractModuleTemplate
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.*
-import org.opendaylight.yangtools.yang.common.QName
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-
-public class AbsModuleGeneratedObjectFactory {
-
-    public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional<String> copyright) {
-        FullyQualifiedName abstractFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractModuleName())
-        Optional<String> classJavaDoc = Optional.fromNullable(mbe.getNullableDescription())
-        AbstractModuleTemplate abstractModuleTemplate = TemplateFactory.abstractModuleTemplateFromMbe(mbe)
-        Optional<String> header = abstractModuleTemplate.headerString;
-        List<FullyQualifiedName> implementedInterfaces = abstractModuleTemplate.getTypeDeclaration().getImplemented().collect {
-            FullyQualifiedName.fromString(it)
-        }
-        Optional<FullyQualifiedName> maybeRegistratorType
-        if (abstractModuleTemplate.isRuntime()) {
-            maybeRegistratorType = Optional.of(FullyQualifiedName.fromString(abstractModuleTemplate.getRegistratorType()))
-        } else {
-            maybeRegistratorType = Optional.absent()
-        }
-
-        return toGeneratedObject(abstractFQN, copyright, header, classJavaDoc, implementedInterfaces,
-                abstractModuleTemplate.getModuleFields(), maybeRegistratorType, abstractModuleTemplate.getMethods(),
-                mbe.yangModuleQName
-        )
-    }
-
-    public GeneratedObject toGeneratedObject(FullyQualifiedName abstractFQN,
-                                             Optional<String> copyright,
-                                             Optional<String> header,
-                                             Optional<String> classJavaDoc,
-                                             List<FullyQualifiedName> implementedInterfaces,
-                                             List<ModuleField> moduleFields,
-                                             Optional<FullyQualifiedName> maybeRegistratorType,
-                                             List<Method> methods,
-                                             QName yangModuleQName) {
-        JavaFileInputBuilder b = new JavaFileInputBuilder()
-
-        Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName)
-        b.addClassAnnotation(moduleQNameAnnotation)
-
-        b.setFqn(abstractFQN)
-        b.setTypeName(TypeName.absClassType)
-
-        b.setCopyright(copyright);
-        b.setHeader(header);
-        b.setClassJavaDoc(classJavaDoc);
-        implementedInterfaces.each { b.addImplementsFQN(it) }
-        if (classJavaDoc.isPresent()) {
-            b.addClassAnnotation("@${Description.canonicalName}(value=\"${classJavaDoc.get()}\")")
-        }
-
-        // add logger:
-        b.addToBody(getLogger(abstractFQN));
-
-        b.addToBody("//attributes start");
-
-        b.addToBody(moduleFields.collect { it.toString() }.join("\n"))
-
-        b.addToBody("//attributes end");
-
-
-        b.addToBody(getCommonFields(abstractFQN));
-
-
-        b.addToBody(getNewConstructor(abstractFQN))
-        b.addToBody(getCopyFromOldConstructor(abstractFQN))
-
-        b.addToBody(getRuntimeRegistratorCode(maybeRegistratorType))
-        b.addToBody(getValidationMethods(moduleFields))
-
-        b.addToBody(getCachesOfResolvedDependencies(moduleFields))
-        b.addToBody(getCachesOfResolvedIdentityRefs(moduleFields))
-        b.addToBody(getGetInstance(moduleFields))
-        b.addToBody(getReuseLogic(moduleFields, abstractFQN))
-        b.addToBody(getEqualsAndHashCode(abstractFQN))
-
-        b.addToBody(getMethods(methods))
-
-        return new GeneratedObjectBuilder(b.build()).toGeneratedObject()
-    }
-
-    private static String getMethods(List<Method> methods) {
-        String result = """
-            // getters and setters
-        """
-        result += methods.collect{it.toString()}.join("\n")
-        return result
-    }
-
-    private static String getEqualsAndHashCode(FullyQualifiedName abstractFQN) {
-        return """
-            @Override
-            public boolean equals(Object o) {
-                if (this == o) return true;
-                if (o == null || getClass() != o.getClass()) return false;
-                ${abstractFQN.typeName} that = (${abstractFQN.typeName}) o;
-                return identifier.equals(that.identifier);
-            }
-
-            @Override
-            public int hashCode() {
-                return identifier.hashCode();
-            }
-        """
-    }
-
-    private static String getReuseLogic(List<ModuleField> moduleFields, FullyQualifiedName abstractFQN) {
-        String result = """
-            public boolean canReuseInstance(${abstractFQN.typeName} oldModule){
-                // allow reusing of old instance if no parameters was changed
-                return isSame(oldModule);
-            }
-
-            public ${AutoCloseable.canonicalName} reuseInstance(${AutoCloseable.canonicalName} oldInstance){
-                // implement if instance reuse should be supported. Override canReuseInstance to change the criteria.
-                return oldInstance;
-            }
-            """
-        // isSame method that detects changed fields
-        result += """
-            public boolean isSame(${abstractFQN.typeName} other) {
-                if (other == null) {
-                    throw new IllegalArgumentException("Parameter 'other' is null");
-                }
-            """
-        // loop through fields, do deep equals on each field
-        result += moduleFields.collect { field ->
-            if (field.isListOfDependencies()) {
-                return """
-                    if (${field.name}Dependency.equals(other.${field.name}Dependency) == false) {
-                        return false;
-                    }
-                    for (int idx = 0; idx < ${field.name}Dependency.size(); idx++) {
-                        if (${field.name}Dependency.get(idx) != other.${field.name}Dependency.get(idx)) {
-                            return false;
-                        }
-                    }
-                """
-            } else if (field.isDependent()) {
-                return """
-                    if (${field.name}Dependency != other.${field.name}Dependency) { // reference to dependency must be same
-                        return false;
-                    }
-                """
-            } else {
-                return """
-                    if (java.util.Objects.deepEquals(${field.name}, other.${field.name}) == false) {
-                        return false;
-                    }
-                """
-            }
-        }.join("\n")
-
-
-        result += """
-                return true;
-            }
-            """
-
-        return result
-    }
-
-    private static String getGetInstance(List<ModuleField> moduleFields) {
-        String result = """
-            @Override
-            public final ${AutoCloseable.canonicalName} getInstance() {
-                if(instance==null) {
-            """
-        // create instance start
-
-        // loop through dependent fields, use dependency resolver to instantiate dependencies. Do it in loop in case field represents list of dependencies.
-        Map<ModuleField, String> resolveDependenciesMap = moduleFields.findAll {
-            it.isDependent()
-        }.collectEntries { ModuleField field ->
-            [field, field.isList() ?
-                    """
-                ${field.name}Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>();
-                for(javax.management.ObjectName dep : ${field.name}) {
-                    ${field.name}Dependency.add(dependencyResolver.resolveInstance(${
-                        field.dependency.sie.exportedOsgiClassName
-                    }.class, dep, ${field.name}JmxAttribute));
-                }
-                """
-                    :
-                    """
-                ${field.name}Dependency = dependencyResolver.resolveInstance(${
-                        field.dependency.sie.exportedOsgiClassName
-                    }.class, ${field.name}, ${field.name}JmxAttribute);
-                """
-            ]
-        }
-        // wrap each field resolvation statement with if !=null when dependency is not mandatory
-        def wrapWithNullCheckClosure = {Map<ModuleField, String> map, predicate -> map.collect { ModuleField key, String value ->
-            predicate(key) ? """
-                if(${key.name}!=null) {
-                    ${value}
-                }
-                """ : value
-            }.join("\n")
-        }
-
-        result += wrapWithNullCheckClosure(resolveDependenciesMap, {ModuleField key ->
-            key.getDependency().isMandatory() == false} )
-
-        // add code to inject dependency resolver to fields that support it
-        Map<ModuleField, String> injectDepsMap = moduleFields.findAll { it.needsDepResolver }.collectEntries { field ->
-            if (field.isList()) {
-                return [field,"""
-                for(${field.genericInnerType} candidate : ${field.name}) {
-                    candidate.injectDependencyResolver(dependencyResolver);
-                }
-                """]
-            } else {
-                return [field, "${field.name}.injectDependencyResolver(dependencyResolver);"]
-            }
-        }
-
-        result += wrapWithNullCheckClosure(injectDepsMap, {true})
-
-        // identity refs need to be injected with dependencyResolver and base class
-        Map<ModuleField, String> resolveIdentityMap = moduleFields.findAll { it.isIdentityRef() }.collectEntries { IdentityRefModuleField field ->
-            [field,
-            "set${field.attributeName}(${field.name}.resolveIdentity(dependencyResolver, ${field.identityBaseClass}.class));"]
-        }
-
-        result += wrapWithNullCheckClosure(resolveIdentityMap, {true})
-
-        // create instance end: reuse and recreate logic
-        result += """
-                    if(oldInstance!=null && canReuseInstance(oldModule)) {
-                        instance = reuseInstance(oldInstance);
-                    } else {
-                        if(oldInstance!=null) {
-                            try {
-                                oldInstance.close();
-                            } catch(Exception e) {
-                                logger.error("An error occurred while closing old instance " + oldInstance, e);
-                            }
-                        }
-                        instance = createInstance();
-                        if (instance == null) {
-                            throw new IllegalStateException("Error in createInstance - null is not allowed as return value");
-                        }
-                    }
-                }
-                return instance;
-            }
-            public abstract ${AutoCloseable.canonicalName} createInstance();
-            """
-        return result
-    }
-
-    private static String getCommonFields(FullyQualifiedName abstractFQN) {
-        return """
-            private final ${abstractFQN.typeName} oldModule;
-            private final ${AutoCloseable.canonicalName} oldInstance;
-            private ${AutoCloseable.canonicalName} instance;
-            private final ${DependencyResolver.canonicalName} dependencyResolver;
-            private final ${ModuleIdentifier.canonicalName} identifier;
-            @Override
-            public ${ModuleIdentifier.canonicalName} getIdentifier() {
-                return identifier;
-            }
-            """
-    }
-
-    private static String getCachesOfResolvedIdentityRefs(List<ModuleField> moduleFields) {
-        return moduleFields.findAll { it.isIdentityRef() }.collect { IdentityRefModuleField field ->
-            "private ${field.identityClassType} ${field.identityClassName};"
-        }.join("\n")
-    }
-
-    private static String getCachesOfResolvedDependencies(List<ModuleField> moduleFields) {
-        return moduleFields.findAll { it.dependent }.collect { field ->
-            if (field.isList()) {
-                return """
-                    private java.util.List<${field.dependency.sie.exportedOsgiClassName}> ${
-                    field.name
-                }Dependency = new java.util.ArrayList<${field.dependency.sie.exportedOsgiClassName}>();
-                    protected final java.util.List<${field.dependency.sie.exportedOsgiClassName}> get${
-                    field.attributeName
-                }Dependency(){
-                        return ${field.name}Dependency;
-                    }
-                    """
-            } else {
-                return """
-                    private ${field.dependency.sie.exportedOsgiClassName} ${field.name}Dependency;
-                    protected final ${field.dependency.sie.exportedOsgiClassName} get${field.attributeName}Dependency(){
-                        return ${field.name}Dependency;
-                    }
-                    """
-            }
-        }.join("\n")
-    }
-
-    private static String getRuntimeRegistratorCode(Optional<FullyQualifiedName> maybeRegistratorType) {
-        if (maybeRegistratorType.isPresent()) {
-            String registratorType = maybeRegistratorType.get()
-
-            return """
-                private ${registratorType} rootRuntimeBeanRegistratorWrapper;
-
-                public ${registratorType} getRootRuntimeBeanRegistratorWrapper(){
-                    return rootRuntimeBeanRegistratorWrapper;
-                }
-
-                @Override
-                public void setRuntimeBeanRegistrator(${RootRuntimeBeanRegistrator.canonicalName} rootRuntimeRegistrator){
-                    this.rootRuntimeBeanRegistratorWrapper = new ${registratorType}(rootRuntimeRegistrator);
-                }
-                """
-        } else {
-            return ""
-        }
-    }
-
-    private static String getValidationMethods(List<ModuleField> moduleFields) {
-        String result = """
-            @Override
-            public void validate() {
-            """
-        // validate each mandatory dependency
-        List<String> lines = moduleFields.findAll{(it.dependent && it.dependency.mandatory)}.collect { field ->
-            if (field.isList()) {
-                return "" +
-                        "for(javax.management.ObjectName dep : ${field.name}) {\n" +
-                        "    dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, dep, ${field.name}JmxAttribute);\n" +
-                        "}\n"
-            } else {
-                return "dependencyResolver.validateDependency(${field.dependency.sie.fullyQualifiedName}.class, ${field.name}, ${field.name}JmxAttribute);"
-            }
-        }
-        result += lines.findAll { it.isEmpty() == false }.join("\n")
-        result += """
-                customValidation();
-            }
-
-            protected void customValidation(){
-            }
-        """
-        return result
-    }
-
-    private static String getLogger(FullyQualifiedName fqn) {
-        return "private static final ${Logger.canonicalName} logger = ${LoggerFactory.canonicalName}.getLogger(${fqn.toString()}.class);"
-    }
-
-    // assumes that each parameter name corresponds to an field in this class, constructs lines setting this.field = field;
-    private static String getConstructorStart(FullyQualifiedName fqn,
-                                              LinkedHashMap<String, String> parameters, String after) {
-        return "public ${fqn.typeName}(" +
-                parameters.collect { it.key + " " + it.value }.join(",") +
-                ") {\n" +
-                parameters.values().collect { "this.${it}=${it};\n" }.join() +
-                after +
-                "}\n"
-    }
-
-    private static String getNewConstructor(FullyQualifiedName abstractFQN) {
-        LinkedHashMap<String, String> parameters = [
-                (ModuleIdentifier.canonicalName): "identifier",
-                (DependencyResolver.canonicalName): "dependencyResolver"
-        ]
-        String setToNulls = ["oldInstance", "oldModule"].collect { "this.${it}=null;\n" }.join()
-        return getConstructorStart(abstractFQN, parameters, setToNulls)
-    }
-
-    private static String getCopyFromOldConstructor(FullyQualifiedName abstractFQN) {
-        LinkedHashMap<String, String> parameters = [
-                (ModuleIdentifier.canonicalName): "identifier",
-                (DependencyResolver.canonicalName): "dependencyResolver",
-                (abstractFQN.typeName): "oldModule",
-                (AutoCloseable.canonicalName): "oldInstance"
-        ]
-        return getConstructorStart(abstractFQN, parameters, "")
-    }
-}
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/AbsModuleGeneratedObjectFactory.java
new file mode 100644 (file)
index 0000000..aa06cb9
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * 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.yangjmxgenerator.plugin.gofactory;
+
+import static java.lang.String.format;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.annotations.Description;
+import org.opendaylight.controller.config.api.runtime.RootRuntimeBeanRegistrator;
+import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractModuleTemplate;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AbsModuleGeneratedObjectFactory {
+
+    public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional<String> copyright) {
+        FullyQualifiedName abstractFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractModuleName());
+        Optional<String> classJavaDoc = Optional.fromNullable(mbe.getNullableDescription());
+        AbstractModuleTemplate abstractModuleTemplate = TemplateFactory.abstractModuleTemplateFromMbe(mbe);
+        Optional<String> header = abstractModuleTemplate.getHeaderString();
+
+        List<FullyQualifiedName> implementedInterfaces = new ArrayList<>();
+        for(String implemented: abstractModuleTemplate.getTypeDeclaration().getImplemented()) {
+            implementedInterfaces.add(FullyQualifiedName.fromString(implemented));
+        }
+        Optional<FullyQualifiedName> maybeRegistratorType;
+        if (abstractModuleTemplate.isRuntime()) {
+            maybeRegistratorType = Optional.of(FullyQualifiedName.fromString(abstractModuleTemplate.getRegistratorType()));
+        } else {
+            maybeRegistratorType = Optional.absent();
+        }
+
+        return toGeneratedObject(abstractFQN, copyright, header, classJavaDoc, implementedInterfaces,
+                abstractModuleTemplate.getModuleFields(), maybeRegistratorType, abstractModuleTemplate.getMethods(),
+                mbe.getYangModuleQName());
+    }
+
+    public GeneratedObject toGeneratedObject(FullyQualifiedName abstractFQN,
+                                             Optional<String> copyright,
+                                             Optional<String> header,
+                                             Optional<String> classJavaDoc,
+                                             List<FullyQualifiedName> implementedInterfaces,
+                                             List<ModuleField> moduleFields,
+                                             Optional<FullyQualifiedName> maybeRegistratorType,
+                                             List<? extends Method> methods,
+                                             QName yangModuleQName) {
+        JavaFileInputBuilder b = new JavaFileInputBuilder();
+
+        Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName);
+        b.addClassAnnotation(moduleQNameAnnotation);
+
+        b.setFqn(abstractFQN);
+        b.setTypeName(TypeName.absClassType);
+
+        b.setCopyright(copyright);
+        b.setHeader(header);
+        b.setClassJavaDoc(classJavaDoc);
+        for(FullyQualifiedName implemented: implementedInterfaces) {
+            b.addImplementsFQN(implemented);
+        }
+        if (classJavaDoc.isPresent()) {
+            b.addClassAnnotation(format("@%s(value=\"%s\")", Description.class.getCanonicalName(), classJavaDoc.get()));
+        }
+
+        // add logger:
+        b.addToBody(getLogger(abstractFQN));
+
+        b.addToBody("//attributes start");
+        for(ModuleField moduleField: moduleFields) {
+            b.addToBody(moduleField.toString() +"\n");
+        }
+
+        b.addToBody("//attributes end");
+
+
+        b.addToBody(getCommonFields(abstractFQN));
+
+
+        b.addToBody(getNewConstructor(abstractFQN));
+        b.addToBody(getCopyFromOldConstructor(abstractFQN));
+
+        b.addToBody(getRuntimeRegistratorCode(maybeRegistratorType));
+        b.addToBody(getValidationMethods(moduleFields));
+
+        b.addToBody(getCachesOfResolvedDependencies(moduleFields));
+        b.addToBody(getCachesOfResolvedIdentityRefs(moduleFields));
+        b.addToBody(getGetInstance(moduleFields));
+        b.addToBody(getReuseLogic(moduleFields, abstractFQN));
+        b.addToBody(getEqualsAndHashCode(abstractFQN));
+
+        b.addToBody(getMethods(methods));
+
+        return new GeneratedObjectBuilder(b.build()).toGeneratedObject();
+    }
+
+    private static String getMethods(List<? extends Method>  methods) {
+        String result = "\n// getters and setters\n";
+        for(Method method: methods) {
+            result += method.toString()+"\n";
+        }
+        return result;
+    }
+
+    private static String getEqualsAndHashCode(FullyQualifiedName abstractFQN) {
+        return "\n"+
+            "@Override\n"+
+            "public boolean equals(Object o) {\n"+
+                "if (this == o) return true;\n"+
+                "if (o == null || getClass() != o.getClass()) return false;\n"+
+                format("%s that = (%1$s) o;\n", abstractFQN.getTypeName())+
+                "return identifier.equals(that.identifier);\n"+
+            "}\n"+
+            "\n"+
+            "@Override\n"+
+            "public int hashCode() {\n"+
+                "return identifier.hashCode();\n"+
+            "}\n";
+    }
+
+    private static String getReuseLogic(List<ModuleField> moduleFields, FullyQualifiedName abstractFQN) {
+        String result = "\n"+
+            format("public boolean canReuseInstance(%s oldModule){\n", abstractFQN.getTypeName())+
+                "// allow reusing of old instance if no parameters was changed\n"+
+                "return isSame(oldModule);\n"+
+            "}\n"+
+            "\n"+
+            format("public %s reuseInstance(%1$s oldInstance){\n", AutoCloseable.class.getCanonicalName())+
+                "// implement if instance reuse should be supported. Override canReuseInstance to change the criteria.\n"+
+                "return oldInstance;\n"+
+            "}\n";
+        // isSame method that detects changed fields
+        result += "\n"+
+            format("public boolean isSame(%s other) {\n", abstractFQN.getTypeName())+
+                "if (other == null) {\n"+
+                    "throw new IllegalArgumentException(\"Parameter 'other' is null\");\n"+
+                "}\n";
+        // loop through fields, do deep equals on each field
+
+        for (ModuleField moduleField : moduleFields) {
+            if (moduleField.isListOfDependencies()) {
+                result += format(
+                    "if (%1$sDependency.equals(other.%1$sDependency) == false) {\n"+
+                        "return false;\n"+
+                    "}\n"+
+                    "for (int idx = 0; idx < %1$sDependency.size(); idx++) {\n"+
+                        "if (%1$sDependency.get(idx) != other.%1$sDependency.get(idx)) {\n"+
+                            "return false;\n"+
+                        "}\n"+
+                    "}\n" ,moduleField.getName());
+            } else if (moduleField.isDependent()) {
+                result += format(
+                    "if (%sDependency != other.%1$sDependency) { // reference to dependency must be same\n"+
+                        "return false;\n"+
+                    "}\n",moduleField.getName());
+            } else {
+                result += format(
+                    "if (java.util.Objects.deepEquals(%s, other.%1$s) == false) {\n"+
+                        "return false;\n"+
+                    "}\n", moduleField.getName());
+            }
+        }
+        result += "\n"+
+                "return true;\n"+
+            "}\n";
+
+        return result;
+    }
+
+    private static String getGetInstance(List<ModuleField> moduleFields) {
+        String result = "\n"+
+            "@Override\n"+
+            format("public final %s getInstance() {\n", AutoCloseable.class.getCanonicalName())+
+                "if(instance==null) {\n";
+        // create instance start
+
+        // loop through dependent fields, use dependency resolver to instantiate dependencies. Do it in loop in case field represents list of dependencies.
+        Map<ModuleField, String> resolveDependenciesMap = new HashMap<>();
+        for(ModuleField moduleField: moduleFields) {
+            if (moduleField.isDependent()) {
+                String str;
+                String osgi = moduleField.getDependency().getSie().getExportedOsgiClassName();
+                if (moduleField.isList()) {
+                    str = format(
+                        "%sDependency = new java.util.ArrayList<%s>();\n"+
+                        "for(javax.management.ObjectName dep : %1$s) {\n"+
+                            "%1$sDependency.add(dependencyResolver.resolveInstance(%2$s.class, dep, %1$sJmxAttribute));\n"+
+                        "}\n", moduleField.getName(), osgi);
+                } else {
+                    str = format(
+                        "%1$sDependency = dependencyResolver.resolveInstance(%2$s.class, %1$s, %1$sJmxAttribute);",
+                        moduleField.getName(), osgi);
+                }
+                resolveDependenciesMap.put(moduleField, str);
+            }
+        }
+
+        // wrap each field resolvation statement with if !=null when dependency is not mandatory
+        for (Map.Entry<ModuleField, String> entry : resolveDependenciesMap.entrySet()) {
+            if (entry.getKey().getDependency().isMandatory() == false) {
+                result += format("if (%s!=null) {\n%s;\n}", entry.getKey().getName(), entry.getValue());
+            } else {
+                result += entry.getValue();
+            }
+        }
+
+        // add code to inject dependency resolver to fields that support it
+        for(ModuleField moduleField: moduleFields) {
+            if (moduleField.isNeedsDepResolver()) {
+                result += format("if (%s!=null){\n", moduleField.getName());
+                if (moduleField.isList()) {
+                    result += format(
+                        "for(%s candidate : %s) {\n"+
+                            "candidate.injectDependencyResolver(dependencyResolver);\n"+
+                        "}\n", moduleField.getGenericInnerType(), moduleField.getName());
+                } else {
+                    result += format("%s.injectDependencyResolver(dependencyResolver);\n", moduleField.getName());
+                }
+                result += "}\n";
+            }
+        }
+
+        // identity refs need to be injected with dependencyResolver and base class
+        for (ModuleField moduleField : moduleFields) {
+            if (moduleField.isIdentityRef()) {
+                result += format("if (%s!=null) {", moduleField.getName());
+                result += format("set%s(%s.resolveIdentity(dependencyResolver, %s.class));",
+                        moduleField.getAttributeName(), moduleField.getName(),
+                        ((IdentityRefModuleField)moduleField).getIdentityBaseClass());
+                result += "}\n";
+            }
+        }
+
+        // create instance end: reuse and recreate logic
+        result +=   "if(oldInstance!=null && canReuseInstance(oldModule)) {\n"+
+                        "instance = reuseInstance(oldInstance);\n"+
+                    "} else {\n"+
+                        "if(oldInstance!=null) {\n"+
+                           "try {\n"+
+                                "oldInstance.close();\n"+
+                            "} catch(Exception e) {\n"+
+                                "logger.error(\"An error occurred while closing old instance \" + oldInstance, e);\n"+
+                            "}\n"+
+                        "}\n"+
+                        "instance = createInstance();\n"+
+                        "if (instance == null) {\n"+
+                            "throw new IllegalStateException(\"Error in createInstance - null is not allowed as return value\");\n"+
+                        "}\n"+
+                    "}\n"+
+                "}\n"+
+                "return instance;\n"+
+            "}\n"+
+            format("public abstract %s createInstance();\n", AutoCloseable.class.getCanonicalName());
+
+        return result;
+    }
+
+    private static String getCommonFields(FullyQualifiedName abstractFQN) {
+        return "\n"+
+            format("private final %s oldModule;\n", abstractFQN.getTypeName())+
+            format("private final %s oldInstance;\n", AutoCloseable.class.getCanonicalName())+
+            format("private %s instance;\n", AutoCloseable.class.getCanonicalName())+
+            format("private final %s dependencyResolver;\n", DependencyResolver.class.getCanonicalName())+
+            format("private final %s identifier;\n", ModuleIdentifier.class.getCanonicalName())+
+            "@Override\n"+
+            format("public %s getIdentifier() {\n", ModuleIdentifier.class.getCanonicalName())+
+                "return identifier;\n"+
+            "}\n";
+    }
+
+    private static String getCachesOfResolvedIdentityRefs(List<ModuleField> moduleFields) {
+        StringBuilder result = new StringBuilder();
+        for (ModuleField moduleField : moduleFields) {
+            if (moduleField.isIdentityRef()) {
+                IdentityRefModuleField field = (IdentityRefModuleField) moduleField;
+                result.append(format("private %s %s;\n", field.getIdentityClassType(), field.getIdentityClassName()));
+            }
+        }
+        return result.toString();
+    }
+
+    private static String getCachesOfResolvedDependencies(List<ModuleField> moduleFields) {
+        StringBuilder result = new StringBuilder();
+        for (ModuleField moduleField: moduleFields) {
+            if (moduleField.isDependent()) {
+                String osgi = moduleField.getDependency().getSie().getExportedOsgiClassName();
+                if (moduleField.isList()) {
+                    result
+                            .append(format("private java.util.List<%s> %sDependency = new java.util.ArrayList<%s>();", osgi, moduleField.getName(), osgi))
+                            .append(format("protected final java.util.List<%s> get%sDependency(){\n", osgi, moduleField.getAttributeName()))
+                            .append(format("return %sDependency;\n", moduleField.getName()))
+                            .append("}\n");
+                } else {
+                    result.append(format(
+                    "private %s %sDependency;\n"+
+                    "protected final %s get%sDependency(){\n"+
+                        "return %sDependency;\n"+
+                    "}",
+                    osgi, moduleField.getName(), osgi, moduleField.getAttributeName(), moduleField.getName()));
+                }
+            }
+        }
+        return result.toString();
+    }
+
+    private static String getRuntimeRegistratorCode(Optional<FullyQualifiedName> maybeRegistratorType) {
+        if (maybeRegistratorType.isPresent()) {
+            String registratorType = maybeRegistratorType.get().toString();
+
+            return "\n"+
+                format("private %s rootRuntimeBeanRegistratorWrapper;\n", registratorType)+
+                "\n"+
+                format("public %s getRootRuntimeBeanRegistratorWrapper(){\n", registratorType)+
+                    "return rootRuntimeBeanRegistratorWrapper;\n"+
+                "}\n"+
+                "\n"+
+                "@Override\n"+
+                format("public void setRuntimeBeanRegistrator(%s rootRuntimeRegistrator){\n", RootRuntimeBeanRegistrator.class.getCanonicalName())+
+                    format("this.rootRuntimeBeanRegistratorWrapper = new %s(rootRuntimeRegistrator);\n", registratorType)+
+                "}\n";
+        } else {
+            return "";
+        }
+    }
+
+    private static String getValidationMethods(List<ModuleField> moduleFields) {
+        String result = "\n"+
+            "@Override\n"+
+            "public void validate() {\n";
+        // validate each mandatory dependency
+        for(ModuleField moduleField: moduleFields) {
+            if (moduleField.isDependent() && moduleField.getDependency().isMandatory()) {
+                if (moduleField.isList()) {
+                    result += "" +
+                            format("for(javax.management.ObjectName dep : %s) {\n", moduleField.getName()) +
+                            format("    dependencyResolver.validateDependency(%s.class, dep, %sJmxAttribute);\n",
+                                    moduleField.getDependency().getSie().getFullyQualifiedName(), moduleField.getName()) +
+                            "}\n";
+                } else {
+                    result += format("dependencyResolver.validateDependency(%s.class, %s, %sJmxAttribute);",
+                            moduleField.getDependency().getSie().getFullyQualifiedName(), moduleField.getName(), moduleField.getName());
+                }
+            }
+        }
+        result += "\n"+
+                "customValidation();\n"+
+            "}\n"+
+            "\n"+
+            "protected void customValidation() {\n"+
+            "}\n";
+        return result;
+    }
+
+    private static String getLogger(FullyQualifiedName fqn) {
+        return format("private static final %s logger = %s.getLogger(%s.class);",
+                Logger.class.getCanonicalName(), LoggerFactory.class.getCanonicalName(), fqn);
+    }
+
+    // assumes that each parameter name corresponds to an field in this class, constructs lines setting this.field = field;
+    private static String getConstructorStart(FullyQualifiedName fqn,
+                                              LinkedHashMap<String, String> parameters, String after) {
+        String paramString = Joiner.on(",").withKeyValueSeparator(" ").join(parameters);
+        String setters = "";
+        for (String paramName : parameters.values()) {
+            setters += format("this.%s = %1$s;\n", paramName);
+        }
+        return format("public %s(", fqn.getTypeName()) +
+                paramString +
+                ") {\n" +
+                setters +
+                after +
+                "}\n";
+    }
+
+    private static String getNewConstructor(FullyQualifiedName abstractFQN) {
+        LinkedHashMap<String, String> parameters = new LinkedHashMap<>();
+        parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier");
+        parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
+
+        String setToNulls = "this.oldInstance=null;\n;" +
+                "this.oldModule=null;\n";
+        return getConstructorStart(abstractFQN, parameters, setToNulls);
+    }
+
+    private static String getCopyFromOldConstructor(FullyQualifiedName abstractFQN) {
+        LinkedHashMap<String, String> parameters = new LinkedHashMap<>();
+        parameters.put(ModuleIdentifier.class.getCanonicalName(), "identifier");
+        parameters.put(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
+        parameters.put(abstractFQN.getTypeName(), "oldModule");
+        parameters.put(AutoCloseable.class.getCanonicalName(), "oldInstance");
+        return getConstructorStart(abstractFQN, parameters, "");
+    }
+}
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.groovy b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.groovy
deleted file mode 100644 (file)
index 6504aac..0000000
+++ /dev/null
@@ -1,40 +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.yangjmxgenerator.plugin.gofactory
-
-import com.google.common.base.Optional
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.FtlTemplate
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder
-import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder
-
-public class GenericGeneratedObjectFactory {
-
-    public GeneratedObject toGeneratedObject(FtlTemplate template, Optional<String> copyright) {
-        JavaFileInputBuilder b = new JavaFileInputBuilder();
-        b.setHeader(template.headerString)
-        b.setFqn(new FullyQualifiedName(template.packageName, template.typeDeclaration.name))
-        b.setClassJavaDoc(template.maybeJavadoc)
-        template.annotations.each { b.addClassAnnotation(it) }
-        // type declaration
-        template.typeDeclaration.extended.each { b.addExtendsFQN(FullyQualifiedName.fromString(it)) }
-        template.typeDeclaration.implemented.each { b.addImplementsFQN(FullyQualifiedName.fromString(it)) }
-        b.setCopyright(copyright);
-        b.setTypeName(template.typeDeclaration.toTypeName())
-        // fields
-        template.fields.each { b.addToBody(it.toString()) }
-        // constructors
-        template.constructors.each { b.addToBody(it.toString()) }
-        // methods
-        template.methods.each { b.addToBody(it.toString()) }
-
-        return new GeneratedObjectBuilder(b.build()).toGeneratedObject();
-    }
-}
diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.java b/opendaylight/config/yang-jmx-generator-plugin/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/plugin/gofactory/GenericGeneratedObjectFactory.java
new file mode 100644 (file)
index 0000000..11bb677
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.yangjmxgenerator.plugin.gofactory;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.FtlTemplate;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Constructor;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Method;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder;
+
+public class GenericGeneratedObjectFactory {
+
+    public GeneratedObject toGeneratedObject(FtlTemplate template, Optional<String> copyright) {
+        JavaFileInputBuilder b = new JavaFileInputBuilder();
+        b.setHeader(template.getHeaderString());
+        b.setFqn(new FullyQualifiedName(template.getPackageName(), template.getTypeDeclaration().getName()));
+        b.setClassJavaDoc(template.getMaybeJavadoc());
+        for (Annotation annotation : template.getAnnotations()) {
+            b.addClassAnnotation(annotation);
+        }
+        // type declaration
+        for (String extended : template.getTypeDeclaration().getExtended()) {
+            b.addExtendsFQN(FullyQualifiedName.fromString(extended));
+        }
+        for (String implemented : template.getTypeDeclaration().getImplemented()) {
+            b.addImplementsFQN(FullyQualifiedName.fromString(implemented));
+        }
+        b.setCopyright(copyright);
+        b.setTypeName(template.getTypeDeclaration().toTypeName());
+        // fields
+        for (Field field : template.getFields()) {
+            b.addToBody(field.toString());
+        }
+        // constructors
+        for (Constructor constructor : template.getConstructors()) {
+            b.addToBody(constructor.toString());
+        }
+        // methods
+        for (Method method : template.getMethods()) {
+            b.addToBody(method.toString());
+        }
+        return new GeneratedObjectBuilder(b.build()).toGeneratedObject();
+    }
+}
index 9d0d6c1888a480aa96042fc2c7824aaf41b5ecbf..234e0feb45047ed2ca14e45e2b2e1dd18432834e 100644 (file)
@@ -22,6 +22,8 @@ netconf.tcp.client.port=8383
 netconf.ssh.address=0.0.0.0
 netconf.ssh.port=1830
 netconf.ssh.pk.path = ./configuration/RSA.pk
+netconf.ssh.default.user = netconf
+netconf.ssh.default.password = netconf
 
 
 netconf.config.persister.active=1,2
index 4a58579b13fd542936f876ddad48c7ebaabcb8a5..167fb21ffdc763f6cda840fc42b6b1e6aed03c7f 100644 (file)
@@ -20,8 +20,8 @@ abstract class AbstractListeningStatsTracker<I, K> extends AbstractStatsTracker<
     private static final Logger logger = LoggerFactory.getLogger(AbstractListeningStatsTracker.class);
     private ListenerRegistration<?> reg;
 
-    protected AbstractListeningStatsTracker(FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    protected AbstractListeningStatsTracker(FlowCapableContext context) {
+        super(context);
     }
 
     protected abstract InstanceIdentifier<?> listenPath();
index c29b6a7730ced4f24374d2e4e67a650f3ed69293..e922656d919f5726de7fe19d743458a26f08a531 100644 (file)
@@ -32,6 +32,9 @@ import com.google.common.util.concurrent.JdkFutureAdapters;
 
 abstract class AbstractStatsTracker<I, K> {
     private static final Logger logger = LoggerFactory.getLogger(AbstractStatsTracker.class);
+    
+    private static final int WAIT_FOR_REQUEST_CYCLE = 2;
+    
     private final FutureCallback<RpcResult<? extends TransactionAware>> callback =
             new FutureCallback<RpcResult<? extends TransactionAware>>() {
         @Override
@@ -62,11 +65,11 @@ abstract class AbstractStatsTracker<I, K> {
 
     private final Map<K, Long> trackedItems = new HashMap<>();
     private final FlowCapableContext context;
-    private final long lifetimeNanos;
+    private long requestCounter;
 
-    protected AbstractStatsTracker(final FlowCapableContext context, final long lifetimeNanos) {
+    protected AbstractStatsTracker(final FlowCapableContext context) {
         this.context = Preconditions.checkNotNull(context);
-        this.lifetimeNanos = lifetimeNanos;
+        this.requestCounter = 0;
     }
 
     protected final InstanceIdentifierBuilder<Node> getNodeIdentifierBuilder() {
@@ -89,24 +92,32 @@ abstract class AbstractStatsTracker<I, K> {
         return context.startDataModification();
     }
 
+    public final synchronized void increaseRequestCounter(){
+        this.requestCounter++;
+    }
     protected abstract void cleanupSingleStat(DataModificationTransaction trans, K item);
     protected abstract K updateSingleStat(DataModificationTransaction trans, I item);
+    public abstract void request();
 
     public final synchronized void updateStats(List<I> list) {
-        final Long expiryTime = System.nanoTime() + lifetimeNanos;
+
         final DataModificationTransaction trans = startTransaction();
 
         for (final I item : list) {
-            trackedItems.put(updateSingleStat(trans, item), expiryTime);
+            trackedItems.put(updateSingleStat(trans, item), requestCounter);
         }
 
         trans.commit();
     }
 
-    public final synchronized void cleanup(final DataModificationTransaction trans, long now) {
+    /**
+     * Statistics will be cleaned up if not update in last two request cycles.
+     * @param trans
+     */
+    public final synchronized void cleanup(final DataModificationTransaction trans) {
         for (Iterator<Entry<K, Long>> it = trackedItems.entrySet().iterator();it.hasNext();){
             Entry<K, Long> e = it.next();
-            if (now > e.getValue()) {
+            if (requestCounter >= e.getValue()+WAIT_FOR_REQUEST_CYCLE) {
                 cleanupSingleStat(trans, e.getKey());
                 it.remove();
             }
index 90ddc28acd0066e72e8e134a49c0a786b6f49b4b..06d6e821122617aa1642e3cfd6a5d46808f8518a 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
+import java.util.Collection;
 import java.util.Map.Entry;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
@@ -37,12 +38,17 @@ import org.slf4j.LoggerFactory;
 final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatisticsMapList, FlowStatsEntry> {
     private static final Logger logger = LoggerFactory.getLogger(FlowStatsTracker.class);
     private final OpendaylightFlowStatisticsService flowStatsService;
+    private FlowTableStatsTracker flowTableStats;
     private int unaccountedFlowsCounter = 1;
 
-    FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context) {
+        super(context);
         this.flowStatsService = flowStatsService;
     }
+    FlowStatsTracker(OpendaylightFlowStatisticsService flowStatsService, final FlowCapableContext context, FlowTableStatsTracker flowTableStats) {
+        this(flowStatsService, context);
+        this.flowTableStats = flowTableStats;
+    }
 
     @Override
     protected void cleanupSingleStat(DataModificationTransaction trans, FlowStatsEntry item) {
@@ -203,6 +209,20 @@ final class FlowStatsTracker extends AbstractListeningStatsTracker<FlowAndStatis
         return "Flow";
     }
 
+    @Override
+    public void request() {
+        // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
+        //        comes back -- we do not have any tables anyway.
+        final Collection<TableKey> tables = flowTableStats.getTables();
+        logger.debug("Node {} supports {} table(s)", this.getNodeRef(), tables.size());
+        for (final TableKey key : tables) {
+            logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), this.getNodeRef());
+            this.requestAggregateFlows(key);
+        }
+
+        this.requestAllFlowsAllTables();
+        
+    }
     public void requestAllFlowsAllTables() {
         if (flowStatsService != null) {
             final GetAllFlowsStatisticsFromAllFlowTablesInputBuilder input = new GetAllFlowsStatisticsFromAllFlowTablesInputBuilder();
index 3fe68c111a1549bc6c9df7b9b19803590ffad94b..a160f6d467ca6731a8c4d485250d6697cec8b97e 100644 (file)
@@ -30,8 +30,8 @@ final class FlowTableStatsTracker extends AbstractStatsTracker<FlowTableAndStati
     private final Set<TableKey> tables = Collections.unmodifiableSet(privateTables);
     private final OpendaylightFlowTableStatisticsService flowTableStatsService;
 
-    FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    FlowTableStatsTracker(OpendaylightFlowTableStatisticsService flowTableStatsService, final FlowCapableContext context) {
+        super(context);
         this.flowTableStatsService = flowTableStatsService;
     }
 
@@ -61,6 +61,7 @@ final class FlowTableStatsTracker extends AbstractStatsTracker<FlowTableAndStati
         return item;
     }
 
+    @Override
     public void request() {
         if (flowTableStatsService != null) {
             final GetFlowTablesStatisticsInputBuilder input = new GetFlowTablesStatisticsInputBuilder();
index 8aebd6b2491a00ce27bfb8e1093517029ea87cf3..e180aaf5fc94de8b609bcab6803843c36da2fac5 100644 (file)
@@ -29,8 +29,8 @@ final class GroupDescStatsTracker extends AbstractListeningStatsTracker<GroupDes
     private static final Logger logger = LoggerFactory.getLogger(GroupDescStatsTracker.class);
     private final OpendaylightGroupStatisticsService groupStatsService;
 
-    public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context, final long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    public GroupDescStatsTracker(OpendaylightGroupStatisticsService groupStatsService, final FlowCapableContext context) {
+        super(context);
         this.groupStatsService = groupStatsService;
     }
 
@@ -70,6 +70,7 @@ final class GroupDescStatsTracker extends AbstractListeningStatsTracker<GroupDes
         return "Group Descriptor";
     }
 
+    @Override
     public void request() {
         if (groupStatsService != null) {
             final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
index 1af8e4e9f1a2cf891795d06f967ca0b12307c730..9735fea069325d7f12a87e02563a9afb24205ccf 100644 (file)
@@ -31,8 +31,8 @@ final class GroupStatsTracker extends AbstractListeningStatsTracker<GroupStats,
     private static final Logger logger = LoggerFactory.getLogger(GroupStatsTracker.class);
     private final OpendaylightGroupStatisticsService groupStatsService;
 
-    GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    GroupStatsTracker(OpendaylightGroupStatisticsService groupStatsService, FlowCapableContext context) {
+        super(context);
         this.groupStatsService = Preconditions.checkNotNull(groupStatsService);
     }
 
@@ -72,6 +72,7 @@ final class GroupStatsTracker extends AbstractListeningStatsTracker<GroupStats,
         return "Group";
     }
 
+    @Override
     public void request() {
         final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
         input.setNode(getNodeRef());
index 4b9592570565fc94d423702a7cff9923d110895f..e8b7fb7164d6d749a4b2427bc9ce591f4f0a5b54 100644 (file)
@@ -29,8 +29,8 @@ final class MeterConfigStatsTracker extends AbstractListeningStatsTracker<MeterC
     private static final Logger logger = LoggerFactory.getLogger(MeterConfigStatsTracker.class);
     private final OpendaylightMeterStatisticsService meterStatsService;
 
-    protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    protected MeterConfigStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) {
+        super(context);
         this.meterStatsService = meterStatsService;
     }
 
@@ -62,6 +62,7 @@ final class MeterConfigStatsTracker extends AbstractListeningStatsTracker<MeterC
         return item;
     }
 
+    @Override
     public void request() {
         if (meterStatsService != null) {
             GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
index 091cbcc1a078f88d54cde3eaa9300da97aaed8c2..b373020f1ca26cbd2e08faa7b033c65731344764 100644 (file)
@@ -29,8 +29,8 @@ final class MeterStatsTracker extends AbstractListeningStatsTracker<MeterStats,
     private static final Logger logger = LoggerFactory.getLogger(MeterStatsTracker.class);
     private final OpendaylightMeterStatisticsService meterStatsService;
 
-    MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    MeterStatsTracker(OpendaylightMeterStatisticsService meterStatsService, final FlowCapableContext context) {
+        super(context);
         this.meterStatsService = meterStatsService;
     }
 
@@ -61,6 +61,7 @@ final class MeterStatsTracker extends AbstractListeningStatsTracker<MeterStats,
         return item;
     }
 
+    @Override
     public void request() {
         if (meterStatsService != null) {
             GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
index 00bd27402fc3c45c82f0f9d06c8a5a562ea76a97..701911d9a2c307c03ecd48c75bfcd4099ba2490f 100644 (file)
@@ -25,8 +25,8 @@ final class NodeConnectorStatsTracker extends AbstractStatsTracker<NodeConnector
     private static final Logger logger = LoggerFactory.getLogger(NodeConnectorStatsTracker.class);
     private final OpendaylightPortStatisticsService portStatsService;
 
-    NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    NodeConnectorStatsTracker(final OpendaylightPortStatisticsService portStatsService, final FlowCapableContext context) {
+        super(context);
         this.portStatsService = portStatsService;
     }
 
@@ -73,6 +73,7 @@ final class NodeConnectorStatsTracker extends AbstractStatsTracker<NodeConnector
         return item;
     }
 
+    @Override
     public void request() {
         if (portStatsService != null) {
             final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
index 5ace260251673bb9fa42b9da14a95a5ece724b4c..dbcbab982a9aec997e37a2fb09e763bb3f3c5f96 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.controller.md.statistics.manager;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -73,6 +72,7 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     private static final int NUMBER_OF_WAIT_CYCLES = 2;
 
     private final MultipartMessageManager msgManager;
+    private final StatisticsRequestScheduler srScheduler;
     private final InstanceIdentifier<Node> targetNodeIdentifier;
     private final FlowStatsTracker flowStats;
     private final FlowTableStatsTracker flowTableStats;
@@ -103,23 +103,25 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
             final OpendaylightGroupStatisticsService groupStatsService,
             final OpendaylightMeterStatisticsService meterStatsService,
             final OpendaylightPortStatisticsService portStatsService,
-            final OpendaylightQueueStatisticsService queueStatsService) {
+            final OpendaylightQueueStatisticsService queueStatsService, 
+            final StatisticsRequestScheduler srScheduler) {
         this.dps = Preconditions.checkNotNull(dps);
         this.targetNodeKey = Preconditions.checkNotNull(nodeKey);
+        this.srScheduler = Preconditions.checkNotNull(srScheduler);
         this.targetNodeIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).build();
         this.targetNodeRef = new NodeRef(targetNodeIdentifier);
 
         final long lifetimeNanos = TimeUnit.MILLISECONDS.toNanos(STATS_COLLECTION_MILLIS * NUMBER_OF_WAIT_CYCLES);
 
         msgManager = new MultipartMessageManager(lifetimeNanos);
-        flowStats = new FlowStatsTracker(flowStatsService, this, lifetimeNanos);
-        flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this, lifetimeNanos);
-        groupDescStats = new GroupDescStatsTracker(groupStatsService, this, lifetimeNanos);
-        groupStats = new GroupStatsTracker(groupStatsService, this, lifetimeNanos);
-        meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this, lifetimeNanos);
-        meterStats = new MeterStatsTracker(meterStatsService, this, lifetimeNanos);
-        nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this, lifetimeNanos);
-        queueStats = new QueueStatsTracker(queueStatsService, this, lifetimeNanos);
+        flowTableStats = new FlowTableStatsTracker(flowTableStatsService, this);
+        flowStats = new FlowStatsTracker(flowStatsService, this, flowTableStats);
+        groupDescStats = new GroupDescStatsTracker(groupStatsService, this);
+        groupStats = new GroupStatsTracker(groupStatsService, this);
+        meterConfigStats = new MeterConfigStatsTracker(meterStatsService, this);
+        meterStats = new MeterStatsTracker(meterStatsService, this);
+        nodeConnectorStats = new NodeConnectorStatsTracker(portStatsService, this);
+        queueStats = new QueueStatsTracker(queueStatsService, this);
     }
 
     public NodeKey getTargetNodeKey() {
@@ -138,7 +140,9 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
 
     @Override
     public DataModificationTransaction startDataModification() {
-        return dps.beginTransaction();
+        DataModificationTransaction dmt = dps.beginTransaction();
+        dmt.registerListener(this.srScheduler);
+        return dmt;
     }
 
     public synchronized void updateGroupDescStats(TransactionAware transaction, List<GroupDescStats> list) {
@@ -186,7 +190,7 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     public synchronized void updateAggregateFlowStats(TransactionAware transaction, AggregateFlowStatistics flowStats) {
         final Short tableId = msgManager.isExpectedTableTransaction(transaction);
         if (tableId != null) {
-            final DataModificationTransaction trans = dps.beginTransaction();
+            final DataModificationTransaction trans = this.startDataModification();
             InstanceIdentifier<Table> tableRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey)
                     .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(tableId)).toInstance();
 
@@ -214,7 +218,7 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     }
 
     public synchronized void updateGroupFeatures(GroupFeatures notification) {
-        final DataModificationTransaction trans = dps.beginTransaction();
+        final DataModificationTransaction trans = this.startDataModification();
 
         final NodeBuilder nodeData = new NodeBuilder();
         nodeData.setKey(targetNodeKey);
@@ -232,7 +236,7 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     }
 
     public synchronized void updateMeterFeatures(MeterFeatures features) {
-        final DataModificationTransaction trans = dps.beginTransaction();
+        final DataModificationTransaction trans = this.startDataModification();
 
         final NodeBuilder nodeData = new NodeBuilder();
         nodeData.setKey(targetNodeKey);
@@ -250,16 +254,15 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     }
 
     public synchronized void cleanStaleStatistics() {
-        final DataModificationTransaction trans = dps.beginTransaction();
-        final long now = System.nanoTime();
-
-        flowStats.cleanup(trans, now);
-        groupDescStats.cleanup(trans, now);
-        groupStats.cleanup(trans, now);
-        meterConfigStats.cleanup(trans, now);
-        meterStats.cleanup(trans, now);
-        nodeConnectorStats.cleanup(trans, now);
-        queueStats.cleanup(trans, now);
+        final DataModificationTransaction trans = this.startDataModification();
+
+        flowStats.cleanup(trans);
+        groupDescStats.cleanup(trans);
+        groupStats.cleanup(trans);
+        meterConfigStats.cleanup(trans);
+        meterStats.cleanup(trans);
+        nodeConnectorStats.cleanup(trans);
+        queueStats.cleanup(trans);
         msgManager.cleanStaleTransactionIds();
 
         trans.commit();
@@ -268,26 +271,23 @@ public final class NodeStatisticsHandler implements AutoCloseable, FlowCapableCo
     public synchronized void requestPeriodicStatistics() {
         logger.debug("Send requests for statistics collection to node : {}", targetNodeKey);
 
-        flowTableStats.request();
-
-        // FIXME: it does not make sense to trigger this before sendAllFlowTablesStatisticsRequest()
-        //        comes back -- we do not have any tables anyway.
-        final Collection<TableKey> tables = flowTableStats.getTables();
-        logger.debug("Node {} supports {} table(s)", targetNodeKey, tables.size());
-        for (final TableKey key : tables) {
-            logger.debug("Send aggregate stats request for flow table {} to node {}", key.getId(), targetNodeKey);
-            flowStats.requestAggregateFlows(key);
-        }
-
-        flowStats.requestAllFlowsAllTables();
-        nodeConnectorStats.request();
-        groupStats.request();
-        groupDescStats.request();
-        meterStats.request();
-        meterConfigStats.request();
-        queueStats.request();
+        this.srScheduler.addRequestToSchedulerQueue(flowTableStats);
+
+        this.srScheduler.addRequestToSchedulerQueue(flowStats);
+        
+        this.srScheduler.addRequestToSchedulerQueue(nodeConnectorStats);
+        
+        this.srScheduler.addRequestToSchedulerQueue(groupStats);
+        
+        this.srScheduler.addRequestToSchedulerQueue(groupDescStats);
+        
+        this.srScheduler.addRequestToSchedulerQueue(meterStats);
+        
+        this.srScheduler.addRequestToSchedulerQueue(meterConfigStats);
+        
+        this.srScheduler.addRequestToSchedulerQueue(queueStats);
     }
-
+    
     public synchronized void start(final Timer timer) {
         flowStats.start(dps);
         groupDescStats.start(dps);
index f187c7082e6e3b2093e2e0b0654a406dd9315950..6f93eeb6172dcdaf24db8301214abe12d92857e0 100644 (file)
@@ -36,8 +36,8 @@ final class QueueStatsTracker extends AbstractListeningStatsTracker<QueueIdAndSt
     private static final Logger logger = LoggerFactory.getLogger(QueueStatsTracker.class);
     private final OpendaylightQueueStatisticsService queueStatsService;
 
-    QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context, long lifetimeNanos) {
-        super(context, lifetimeNanos);
+    QueueStatsTracker(OpendaylightQueueStatisticsService queueStatsService, final FlowCapableContext context) {
+        super(context);
         this.queueStatsService = queueStatsService;
     }
 
@@ -82,6 +82,7 @@ final class QueueStatsTracker extends AbstractListeningStatsTracker<QueueIdAndSt
         return queueEntry;
     }
 
+    @Override
     public void request() {
         if (queueStatsService != null) {
             GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
index 892d304daa8d6cd20c7010082f2698cb8de90266..d8bea7c63a4606fffaed51a9dce5fe889dca2d36 100644 (file)
@@ -66,9 +66,12 @@ public class StatisticsProvider implements AutoCloseable {
     private OpendaylightFlowTableStatisticsService flowTableStatsService;
 
     private OpendaylightQueueStatisticsService queueStatsService;
+    
+    private final StatisticsRequestScheduler srScheduler;
 
     public StatisticsProvider(final DataProviderService dataService) {
         this.dps = Preconditions.checkNotNull(dataService);
+        this.srScheduler = new StatisticsRequestScheduler();
     }
 
     private final StatisticsListener updateCommiter = new StatisticsListener(StatisticsProvider.this);
@@ -86,7 +89,8 @@ public class StatisticsProvider implements AutoCloseable {
         portStatsService = rpcRegistry.getRpcService(OpendaylightPortStatisticsService.class);
         flowTableStatsService = rpcRegistry.getRpcService(OpendaylightFlowTableStatisticsService.class);
         queueStatsService = rpcRegistry.getRpcService(OpendaylightQueueStatisticsService.class);
-
+        this.srScheduler.start();
+        
         // Start receiving notifications
         this.listenerRegistration = nps.registerNotificationListener(this.updateCommiter);
 
@@ -144,7 +148,7 @@ public class StatisticsProvider implements AutoCloseable {
 
             final NodeStatisticsHandler h = new NodeStatisticsHandler(dps, key,
                     flowStatsService, flowTableStatsService, groupStatsService,
-                    meterStatsService, portStatsService, queueStatsService);
+                    meterStatsService, portStatsService, queueStatsService,srScheduler);
             final NodeStatisticsHandler old = handlers.putIfAbsent(key.getId(), h);
             if (old == null) {
                 spLogger.debug("Started node handler for {}", key.getId());
diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/StatisticsRequestScheduler.java
new file mode 100644 (file)
index 0000000..9ebfd6f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright IBM Corporation, 2013.  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.md.statistics.manager;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Main responsibility of the class is to check the MD-SAL data store read/write
+ * transaction accumulation level and send statistics request if number of pending 
+ * read/write transactions are zero.
+ * @author avishnoi@in.ibm.com
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class StatisticsRequestScheduler implements DataTransactionListener {
+
+    private static final Logger srsLogger = LoggerFactory.getLogger(StatisticsRequestScheduler.class);
+    private final Timer timer = new Timer("request-monitor", true);
+
+    // We need ordered retrieval, and O(1) contains operation
+    private final Map<AbstractStatsTracker,Integer> requestQueue = 
+            Collections.synchronizedMap(new LinkedHashMap<AbstractStatsTracker,Integer>());
+    
+    private Long PendingTransactions;
+    
+    private long lastRequestTime = System.nanoTime();
+    
+    private static final long REQUEST_MONITOR_INTERVAL = 1000;
+    
+    private final TimerTask task = new TimerTask() {
+        @Override
+        public void run() {
+            long now = System.nanoTime();
+            if(now > lastRequestTime+TimeUnit.MILLISECONDS.toNanos(REQUEST_MONITOR_INTERVAL)){
+                requestStatistics();
+            }
+        }
+    };
+
+    public StatisticsRequestScheduler(){
+        PendingTransactions = (long) 0;
+    }
+    
+    public void addRequestToSchedulerQueue(AbstractStatsTracker statsRequest){
+        requestQueue.put(statsRequest, null);
+    }
+    
+    public AbstractStatsTracker getNextRequestFromSchedulerQueue(){
+        //Remove first element
+        AbstractStatsTracker stats = null;
+        synchronized(requestQueue){
+            Iterator<Map.Entry<AbstractStatsTracker, Integer>> nodesItr = requestQueue.entrySet().iterator();
+            if(nodesItr.hasNext()){
+                stats = nodesItr.next().getKey();
+                srsLogger.debug("{} chosen up for execution",stats.getNodeRef());
+                nodesItr.remove();
+                return stats;
+            }
+        }
+        return stats;
+    }
+
+    private void requestStatistics(){
+        AbstractStatsTracker stats = this.getNextRequestFromSchedulerQueue();
+        if(stats != null) {
+            stats.request();
+            stats.increaseRequestCounter();
+        }
+    }
+    @Override
+    public void onStatusUpdated(DataModificationTransaction transaction, TransactionStatus status) {
+        
+        AbstractStatsTracker stats = null;
+        synchronized(PendingTransactions){
+            switch(status){
+            case SUBMITED:
+                this.PendingTransactions++;
+                break;
+            case COMMITED:
+            case FAILED:
+                this.PendingTransactions--;
+                if(PendingTransactions == 0){
+                    lastRequestTime = System.nanoTime();
+                    stats = this.getNextRequestFromSchedulerQueue();
+                }
+                srsLogger.debug("Pending MD-SAL transactions : {} & Scheduler queue size : {}",this.PendingTransactions,this.requestQueue.size());
+                break;
+            default:
+                break;
+            }
+        }
+        if(stats != null){
+            stats.request();
+            stats.increaseRequestCounter();
+        }
+    }
+    
+    public void start(){
+        timer.schedule(task, 0, REQUEST_MONITOR_INTERVAL);
+    }
+}
index 857cc3e2e5f2d52e411f2526a5561be94e481a35..b77d92e7cb662aecdd4421d7097f0bf6b909988c 100644 (file)
@@ -13,6 +13,20 @@ import ch.ethz.ssh2.Session;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import io.netty.channel.ChannelFuture;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
 import junit.framework.Assert;
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
@@ -52,22 +66,6 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.xml.sax.SAXException;
-
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
 import static java.util.Collections.emptyList;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -411,7 +409,7 @@ public class NetconfITTest extends AbstractNetconfConfigTest {
                     try {
                         c = sess.getStdout().read(bytes);
                     } catch (IOException e) {
-                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+                        throw new IllegalStateException("IO exception while reading data on ssh bridge.");
                     }
                     logger.info("got data:" + bytes);
                     if (c == 0) {
index 6ddc8ebb55752dca439e63ee3e70dfa260e79783..2e9a0b9d8bbd256154ff82689e85e556b60c9e90 100644 (file)
@@ -7,42 +7,26 @@
  */
 package org.opendaylight.controller.netconf.ssh.authentication;
 
+import java.io.IOException;
 import org.opendaylight.controller.sal.authorization.AuthResultEnum;
-import org.opendaylight.controller.sal.authorization.UserLevel;
 import org.opendaylight.controller.usermanager.IUserManager;
-import org.opendaylight.controller.usermanager.UserConfig;
-
-import java.util.ArrayList;
-import java.util.List;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 
 public class AuthProvider implements AuthProviderInterface {
 
-    private static IUserManager um; //FIXME static mutable state, no locks
-    private static final String DEFAULT_USER = "netconf";
-    private static final String DEFAULT_PASSWORD = "netconf";
+    private IUserManager um;
     private final String pem;
 
-    public AuthProvider(IUserManager ium, String pemCertificate) throws Exception {
+    public AuthProvider(IUserManager ium, String pemCertificate) throws IllegalArgumentException, IOException {
         checkNotNull(pemCertificate, "Parameter 'pemCertificate' is null");
-        AuthProvider.um = ium;
-        if (AuthProvider.um == null) {
-            throw new Exception("No usermanager service available.");
-        }
-
-        List<String> roles = new ArrayList<String>(1);
-        roles.add(UserLevel.SYSTEMADMIN.toString());
-        AuthProvider.um.addLocalUser(new UserConfig(DEFAULT_USER, DEFAULT_PASSWORD, roles)); //FIXME hardcoded auth
+        checkNotNull(ium, "No user manager service available.");
+        this.um = ium;
         pem = pemCertificate;
     }
 
     @Override
     public boolean authenticated(String username, String password) {
-        if (AuthProvider.um == null) {
-            throw new IllegalStateException("No usermanager service available.");
-        }
-        AuthResultEnum authResult = AuthProvider.um.authenticate(username, password);
+        AuthResultEnum authResult = this.um.authenticate(username, password);
         return authResult.equals(AuthResultEnum.AUTH_ACCEPT) || authResult.equals(AuthResultEnum.AUTH_ACCEPT_LOC);
     }
 
@@ -53,11 +37,11 @@ public class AuthProvider implements AuthProviderInterface {
 
     @Override
     public void removeUserManagerService() {
-        AuthProvider.um = null;
+        this.um = null;
     }
 
     @Override
     public void addUserManagerService(IUserManager userManagerService) {
-        AuthProvider.um = userManagerService;
+        this.um = userManagerService;
     }
 }
index 5b8803001ca9a33f71d2cacab990f03891a6891e..ca0c9454d4a5c8934a96da245b41029198e464d6 100644 (file)
@@ -8,12 +8,21 @@
 package org.opendaylight.controller.netconf.ssh.osgi;
 
 import com.google.common.base.Optional;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.authentication.PEMGenerator;
 import org.opendaylight.controller.netconf.util.osgi.NetconfConfigUtil;
+import org.opendaylight.controller.sal.authorization.UserLevel;
 import org.opendaylight.controller.usermanager.IUserManager;
+import org.opendaylight.controller.usermanager.UserConfig;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -21,16 +30,12 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.InetSocketAddress;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Activator for netconf SSH bundle which creates SSH bridge between netconf client and netconf server. Activator
  * starts SSH Server in its own thread. This thread is closed when activator calls stop() method. Server opens socket
- * and listen for client connections. Each client connection creation is handled in separate
+ * and listens for client connections. Each client connection creation is handled in separate
  * {@link org.opendaylight.controller.netconf.ssh.threads.SocketThread} thread.
  * This thread creates two additional threads {@link org.opendaylight.controller.netconf.ssh.threads.IOThread}
  * forwarding data from/to client.IOThread closes servers session and server connection when it gets -1 on input stream.
@@ -44,6 +49,8 @@ public class NetconfSSHActivator implements BundleActivator{
     private static final String EXCEPTION_MESSAGE = "Netconf ssh bridge is not available.";
     private IUserManager iUserManager;
     private BundleContext context = null;
+    private Optional<String> defaultPassword;
+    private Optional<String> defaultUser;
 
     private ServiceTrackerCustomizer<IUserManager, IUserManager> customizer = new ServiceTrackerCustomizer<IUserManager, IUserManager>(){
         @Override
@@ -79,20 +86,23 @@ public class NetconfSSHActivator implements BundleActivator{
 
     @Override
     public void stop(BundleContext context) throws IOException {
+        if (this.defaultUser.isPresent()){
+            this.iUserManager.removeLocalUser(this.defaultUser.get());
+        }
         if (server != null){
             server.stop();
             logger.trace("Netconf SSH bridge is down ...");
         }
     }
     private void startSSHServer() throws IllegalStateException, IOException {
+        checkNotNull(this.iUserManager, "No user manager service available.");
         logger.trace("Starting netconf SSH  bridge.");
         Optional<InetSocketAddress> sshSocketAddressOptional = NetconfConfigUtil.extractSSHNetconfAddress(context, EXCEPTION_MESSAGE);
         InetSocketAddress tcpSocketAddress = NetconfConfigUtil.extractTCPNetconfAddress(context,
                 EXCEPTION_MESSAGE, true);
 
         if (sshSocketAddressOptional.isPresent()){
-            String path = NetconfConfigUtil.getPrivateKeyPath(context);
-            path = path.replace("\\", "/");  // FIXME: shouldn't this convert lines to system dependent path separator?
+            String path =  FilenameUtils.separatorsToSystem(NetconfConfigUtil.getPrivateKeyPath(context));
             if (path.equals("")){
                 throw new IllegalStateException("Missing netconf.ssh.pk.path key in configuration file.");
             }
@@ -100,11 +110,10 @@ public class NetconfSSHActivator implements BundleActivator{
             File privateKeyFile = new File(path);
             String privateKeyPEMString = null;
             if (privateKeyFile.exists() == false) {
-                // generate & save to file
                 try {
                     privateKeyPEMString = PEMGenerator.generateTo(privateKeyFile);
                 } catch (Exception e) {
-                    logger.error("Exception occured while generating PEM string {}",e);
+                    logger.error("Exception occurred while generating PEM string {}",e);
                 }
             } else {
                 // read from file
@@ -117,6 +126,17 @@ public class NetconfSSHActivator implements BundleActivator{
             }
             AuthProvider authProvider = null;
             try {
+                this.defaultPassword = NetconfConfigUtil.getSSHDefaultPassword(context);
+                this.defaultUser = NetconfConfigUtil.getSSHDefaultUser(context);
+                // Since there is no user data store yet (ldap, ...) this adds default user/password to UserManager
+                // if these parameters are set in netconf configuration file.
+                if (defaultUser.isPresent() &&
+                        defaultPassword.isPresent()){
+                    logger.trace(String.format("Default username and password for netconf ssh bridge found. Adding user %s to user manager.",defaultUser.get()));
+                    List<String> roles = new ArrayList<String>(1);
+                    roles.add(UserLevel.SYSTEMADMIN.toString());
+                    iUserManager.addLocalUser(new UserConfig(defaultUser.get(), defaultPassword.get(), roles));
+                }
                 authProvider = new AuthProvider(iUserManager, privateKeyPEMString);
             } catch (Exception e) {
                 logger.error("Error instantiating AuthProvider {}",e);
index b23a2d6697b2ab5623431741fb0ecb374cb22411..f89df2ac7cc331908f64ed8d05b2dc826f4d7757 100644 (file)
@@ -9,12 +9,11 @@
 package org.opendaylight.controller.netconf.util.osgi;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import java.net.InetSocketAddress;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import java.net.InetSocketAddress;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 
 public final class NetconfConfigUtil {
@@ -32,6 +31,8 @@ public final class NetconfConfigUtil {
     private static final String ADDRESS_SUFFIX_PROP = ".address";
     private static final String CLIENT_PROP = ".client";
     private static final String PRIVATE_KEY_PATH_PROP = ".pk.path";
+    private static final String SSH_DEFAULT_USER = ".default.user";
+    private static final String SSH_DEFAULT_PASSWORD = ".default.password";
 
     private static final String CONNECTION_TIMEOUT_MILLIS_PROP = "connectionTimeoutMillis";
     private static final long DEFAULT_TIMEOUT_MILLIS = 5000;
@@ -72,6 +73,13 @@ public final class NetconfConfigUtil {
     public static String getPrivateKeyPath(BundleContext context){
         return getPropertyValue(context,PREFIX_PROP + InfixProp.ssh +PRIVATE_KEY_PATH_PROP);
     }
+    public static Optional<String> getSSHDefaultUser(BundleContext context){
+        return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_USER);
+    }
+    public static Optional<String> getSSHDefaultPassword(BundleContext context){
+        return getOptionalPropertyValue(context,PREFIX_PROP + InfixProp.ssh +SSH_DEFAULT_PASSWORD);
+    }
+
     private static String getPropertyValue(BundleContext context, String propertyName){
         String propertyValue = context.getProperty(propertyName);
         if (propertyValue == null){
@@ -79,6 +87,13 @@ public final class NetconfConfigUtil {
         }
         return propertyValue;
     }
+    private static Optional<String> getOptionalPropertyValue(BundleContext context, String propertyName){
+        String propertyValue = context.getProperty(propertyName);
+        if (Strings.isNullOrEmpty(propertyValue)){
+            return Optional.absent();
+        }
+        return Optional.fromNullable(propertyValue);
+    }
     /**
      * @param context
      *            from which properties are being read.