</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>
+++ /dev/null
-/*
- * 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
- }
-
-}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
+++ /dev/null
-/*
- * 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, "")
- }
-}
--- /dev/null
+/*
+ * 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, "");
+ }
+}
+++ /dev/null
-/*
- * 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();
- }
-}
--- /dev/null
+/*
+ * 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();
+ }
+}
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
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();
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
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() {
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();
}
*/
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;
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) {
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();
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;
}
return item;
}
+ @Override
public void request() {
if (flowTableStatsService != null) {
final GetFlowTablesStatisticsInputBuilder input = new GetFlowTablesStatisticsInputBuilder();
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;
}
return "Group Descriptor";
}
+ @Override
public void request() {
if (groupStatsService != null) {
final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
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);
}
return "Group";
}
+ @Override
public void request() {
final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
input.setNode(getNodeRef());
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;
}
return item;
}
+ @Override
public void request() {
if (meterStatsService != null) {
GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
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;
}
return item;
}
+ @Override
public void request() {
if (meterStatsService != null) {
GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
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;
}
return item;
}
+ @Override
public void request() {
if (portStatsService != null) {
final GetAllNodeConnectorsStatisticsInputBuilder input = new GetAllNodeConnectorsStatisticsInputBuilder();
*/
package org.opendaylight.controller.md.statistics.manager;
-import java.util.Collection;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
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;
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() {
@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) {
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();
}
public synchronized void updateGroupFeatures(GroupFeatures notification) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
final NodeBuilder nodeData = new NodeBuilder();
nodeData.setKey(targetNodeKey);
}
public synchronized void updateMeterFeatures(MeterFeatures features) {
- final DataModificationTransaction trans = dps.beginTransaction();
+ final DataModificationTransaction trans = this.startDataModification();
final NodeBuilder nodeData = new NodeBuilder();
nodeData.setKey(targetNodeKey);
}
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();
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);
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;
}
return queueEntry;
}
+ @Override
public void request() {
if (queueStatsService != null) {
GetAllQueuesStatisticsFromAllPortsInputBuilder input = new GetAllQueuesStatisticsFromAllPortsInputBuilder();
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);
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);
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());
--- /dev/null
+/*
+ * 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);
+ }
+}
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;
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;
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) {
*/
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);
}
@Override
public void removeUserManagerService() {
- AuthProvider.um = null;
+ this.um = null;
}
@Override
public void addUserManagerService(IUserManager userManagerService) {
- AuthProvider.um = userManagerService;
+ this.um = userManagerService;
}
}
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;
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.
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
@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.");
}
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
}
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);
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 {
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;
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){
}
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.