<artifactId>clustered-datastore.integrationtest</artifactId>
<version>0.4.0-SNAPSHOT</version>
- <dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.4.01</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-broker-impl</artifactId>
<version>1.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>xml-apis</artifactId>
+ <groupId>xml-apis</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>reflections</artifactId>
+ <groupId>org.reflections</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-netconf-connector</artifactId>
<version>${netconf.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>xml-apis</artifactId>
+ <groupId>xml-apis</groupId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<module>sal-binding-broker</module>
<module>sal-binding-util</module>
+ <module>sal-binding-dom-it</module>
<!-- Samples -->
<module>samples</module>
<dependencyManagement>
<dependencies>
-
-
-
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.4.01</version>
+ </dependency>
<!-- YANG Tools Dependencies -->
<dependency>
</execution>
</executions>
</plugin>
+
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9-RC1</version>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<groupId>org.eclipse.xtend</groupId>
<artifactId>org.eclipse.xtend.lib</artifactId>
</dependency>
- <dependency>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>org.eclipse.xtend.standalone</artifactId>
- <version>2.4.3</version>
- <scope>runtime</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-binding-config</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-service</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-management</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-flow-statistics</artifactId>
- <version>1.0-SNAPSHOT</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.reflections</groupId>
- <artifactId>reflections</artifactId>
- <version>0.9.9-RC1</version>
- <scope>test</scope>
- </dependency>
</dependencies>
</project>
Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
@SuppressWarnings("rawtypes")
- private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
+ private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
}
return weakRef.get();
}
-
+
@Override
- public void putPathToClass(List<QName> names,Class<?> cls) {
+ public void putPathToClass(List<QName> names, Class<?> cls) {
Type reference = Types.typeForClass(cls);
- pathToInstantiatedType.put(names, reference );
+ pathToInstantiatedType.put(names, reference);
bindingClassEncountered(cls);
}
-
@Override
public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
@SuppressWarnings("unchecked")
return potential;
}
ConcreteType typeref = Types.typeForClass(caseClass);
- ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
+ ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
+ checkState(caseCodec != null, "Case Codec was not created proactivelly for %s", caseClass.getName());
+ checkState(caseCodec.getSchema() != null, "Case schema is not available for %s", caseClass.getName());
@SuppressWarnings("unchecked")
- Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
+ Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
BindingCodec newInstance = newInstanceOf(newCodec);
caseCodec.setDelegate(newInstance);
caseCodecs.put(caseClass, caseCodec);
for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
.getValue().getName());
+
+ LOG.info("Case path: {} Type : {}", caseNode.getKey(), caseNode.getValue().getFullyQualifiedName());
+ pathToType.put(caseNode.getKey(), caseNode.getValue());
+
ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
+
if (node == null) {
LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
typeref.getFullyQualifiedName(), caseNode.getKey());
+ @SuppressWarnings("rawtypes")
+ ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
+ typeToCaseCodecs.putIfAbsent(typeref, value);
continue;
}
-
- pathToType.put(caseNode.getKey(), caseNode.getValue());
@SuppressWarnings("rawtypes")
ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
- typeToCaseNodes.putIfAbsent(typeref, value);
+ typeToCaseCodecs.putIfAbsent(typeref, value);
}
}
choiceCodecs.put(choiceClass, newCodec);
CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class<?>, BindingCodec<?, ?>>) classToCaseRawCodec);
CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
-
+
tryToCreateCasesCodecs(schema);
}
private void tryToCreateCasesCodecs(ChoiceNode schema) {
- for(ChoiceCaseNode caseNode : schema.getCases()) {
+ for (ChoiceCaseNode caseNode : schema.getCases()) {
SchemaPath path = caseNode.getPath();
GeneratedTypeBuilder type;
- if(path != null && (type = pathToType.get(path)) != null) {
+ if (path != null && (type = pathToType.get(path)) != null) {
+ ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
+ ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref);
+ if(partialCodec.getSchema() == null ) {
+ partialCodec.setSchema(caseNode);
+ }
+
Class<?> caseClass = ClassLoaderUtils.tryToLoadClassWithTCCL(type.getFullyQualifiedName());
- if(caseClass != null) {
+ if (caseClass != null) {
getCaseCodecFor(caseClass);
}
}
}
@Override
- public void onDataContainerCodecCreated(Class<?> dataClass,
- Class<? extends BindingCodec<?,?>> dataCodec) {
+ public void onDataContainerCodecCreated(Class<?> dataClass, Class<? extends BindingCodec<?, ?>> dataCodec) {
if (Augmentable.class.isAssignableFrom(dataClass)) {
AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
@SuppressWarnings("rawtypes")
private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
Delegator<BindingCodec> {
- private final boolean augmenting;
+ private boolean augmenting;
private BindingCodec delegate;
- private final Set<String> validNames;
- private final Set<QName> validQNames;
+ private Set<String> validNames;
+ private Set<QName> validQNames;
private ChoiceCaseNode schema;
- public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
- this.delegate = NOT_READY_CODEC;
+ public void setSchema(ChoiceCaseNode caseNode) {
+ this.schema = schema;
this.schema = caseNode;
validNames = new HashSet<>();
validQNames = new HashSet<>();
augmenting = caseNode.isAugmenting();
}
+ public ChoiceCaseCodecImpl() {
+ this.delegate = NOT_READY_CODEC;
+ }
+
+ public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
+ this.delegate = NOT_READY_CODEC;
+ setSchema(caseNode);
+ }
+
@Override
public ValueWithQName<T> deserialize(Node<?> input) {
throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
for (entry : newBinding.moduleContexts.entrySet) {
registry.onModuleContextAdded(schemaContext, entry.key, entry.value);
-
+ binding.pathToType.putAll(entry.value.childNodes)
//val module = entry.key;
val context = entry.value;
updateBindingFor(context.childNodes, schemaContext);
}
private def void updateBindingFor(Map<SchemaPath, GeneratedTypeBuilder> map, SchemaContext module) {
+
for (entry : map.entrySet) {
val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key);
//LOG.info("{} : {}",entry.key,entry.value.fullyQualifiedName)
+ val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
+ typeToDefinition.put(typeRef, entry.value);
if (schemaNode != null) {
- val typeRef = new ReferencedTypeImpl(entry.value.packageName,entry.value.name)
typeToSchemaNode.put(typeRef, schemaNode);
- typeToDefinition.put(typeRef, entry.value);
updatePromisedSchemas(typeRef, schemaNode);
}
+
}
}
import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
import org.opendaylight.yangtools.yang.model.util.ExtendedType
import org.opendaylight.yangtools.yang.model.util.EnumerationType
+import static com.google.common.base.Preconditions.*
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
class TransformerGenerator {
@Property
var Map<Type, GeneratedTypeBuilder> typeToDefinition = new ConcurrentHashMap();
+ @Property
+ var Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap();
+
@Property
var Map<Type, SchemaNode> typeToSchemaNode = new ConcurrentHashMap();
val ref = Types.typeForClass(inputType)
val node = typeToSchemaNode.get(ref)
val typeSpecBuilder = typeToDefinition.get(ref)
+ checkState(typeSpecBuilder !== null, "Could not find typedefinition for %s", inputType.name);
+ val typeSpec = typeSpecBuilder.toInstance();
+ val newret = generateTransformerFor(inputType, typeSpec, node);
+ listener.onClassProcessed(inputType);
+ return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ ]
+ }
+
+ def Class<? extends BindingCodec<Map<QName, Object>, Object>> transformerFor(Class<?> inputType, DataSchemaNode node) {
+ return withClassLoaderAndLock(inputType.classLoader, lock) [ |
+ val ret = getGeneratedClass(inputType)
+ if (ret !== null) {
+ listener.onClassProcessed(inputType);
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ }
+ val ref = Types.typeForClass(inputType)
+ var typeSpecBuilder = typeToDefinition.get(ref)
+ if (typeSpecBuilder == null) {
+ typeSpecBuilder = pathToType.get(node.path);
+ }
+ checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
val typeSpec = typeSpecBuilder.toInstance();
val newret = generateTransformerFor(inputType, typeSpec, node);
listener.onClassProcessed(inputType);
keyTransformerFor(cls, type, node);
}
- private def serializer(Type type) {
+ private def serializer(Type type, DataSchemaNode node) {
val cls = loadClassWithTCCL(type.resolvedName);
-
- transformerFor(cls);
-
+ transformerFor(cls, node);
}
private def Class<?> getValueSerializer(GeneratedTransferObject type) {
]
val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class<? extends BindingCodec<Object, Object>>
- listener?.onDataContainerCodecCreated(inputType,ret);
+ listener?.onDataContainerCodecCreated(inputType, ret);
log.info("DOM Codec for {} was generated {}", inputType, ret)
return ret;
} catch (Exception e) {
Object _listItem = _iterator.next();
_is_empty = false;
//System.out.println(" item" + _listItem);
- Object _value = «type.actualTypeArguments.get(0).serializer.resolvedName».fromDomStatic(_localQName,_listItem);
+ Object _value = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».fromDomStatic(_localQName,_listItem);
//System.out.println(" value" + _value);
«propertyName».add(_value);
_hasNext = _iterator.hasNext();
if(_dom_«propertyName»_list != null && _dom_«propertyName»_list.size() > 0) {
_is_empty = false;
java.util.Map _dom_«propertyName» = (java.util.Map) _dom_«propertyName»_list.get(0);
- «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
+ «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_dom_«propertyName»);
}
'''
private def dispatch CharSequence deserializeProperty(ChoiceNode schema, Type type, String propertyName) '''
- «type.resolvedName» «propertyName» = «type.serializer.resolvedName».fromDomStatic(_localQName,_compositeNode);
+ «type.resolvedName» «propertyName» = «type.serializer(schema).resolvedName».fromDomStatic(_localQName,_compositeNode);
if(«propertyName» != null) {
_is_empty = false;
}
boolean _hasNext = _iterator.hasNext();
while(_hasNext) {
Object _listItem = _iterator.next();
- Object _domValue = «type.actualTypeArguments.get(0).serializer.resolvedName».toDomStatic(_resultName,_listItem);
+ Object _domValue = «type.actualTypeArguments.get(0).serializer(schema).resolvedName».toDomStatic(_resultName,_listItem);
_childNodes.add(_domValue);
_hasNext = _iterator.hasNext();
}
String propertyName) '''
«type.resolvedName» «propertyName» = value.«propertyName»();
if(«propertyName» != null) {
- java.util.List domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+ java.util.List domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
_childNodes.addAll(domValue);
}
'''
String propertyName) '''
«type.resolvedName» «propertyName» = value.«propertyName»();
if(«propertyName» != null) {
- Object domValue = «type.serializer.resolvedName».toDomStatic(_resultName,«propertyName»);
+ Object domValue = «type.serializer(container).resolvedName».toDomStatic(_resultName,«propertyName»);
_childNodes.add(domValue);
}
'''
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import com.google.common.base.Joiner;
import com.google.common.base.Optional;
public final class ClassLoaderUtils {
if ("byte[]".equals(name)) {
return byte[].class;
}
-
- return Thread.currentThread().getContextClassLoader().loadClass(name);
+ try {
+ return Thread.currentThread().getContextClassLoader().loadClass(name);
+ } catch (ClassNotFoundException e) {
+ String[] components = name.split("\\.");
+ String potentialOuter;
+ int length = components.length;
+ if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) {
+
+ String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
+ String innerName = outerName + "$" + components[length-1];
+ return Thread.currentThread().getContextClassLoader().loadClass(innerName);
+ } else {
+ throw e;
+ }
+ }
}
public static Class<?> tryToLoadClassWithTCCL(String fullyQualifiedName) {
try {
return loadClassWithTCCL(fullyQualifiedName);
} catch (ClassNotFoundException e) {
-
+
}
return null;
}
import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory;
+import org.opendaylight.controller.sal.binding.test.util.BindingTestContext;
import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.data.DataStore;
protected org.opendaylight.controller.sal.core.api.data.DataProviderService biDataService;
protected DataProviderService baDataService;
-
- /**
- * Workaround for JUNIT sharing classloaders
- *
- */
- protected static final ClassPool POOL = new ClassPool();
-
- protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
protected BindingIndependentMappingService mappingService;
- protected DataBrokerImpl baDataImpl;
- protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
- protected ListeningExecutorService executor;
- protected BindingIndependentDataServiceConnector connectorServiceImpl;
- protected HashMapDataStore rawDataStore;
- protected SchemaAwareDataStoreAdapter schemaAwareDataStore;
private DataStoreStatsWrapper dataStoreStats;
-
protected DataStore dataStore;
+ protected BindingTestContext testContext;
@Before
public void setUp() {
- executor = MoreExecutors.sameThreadExecutor();
- baDataImpl = new DataBrokerImpl();
- baDataService = baDataImpl;
- baDataImpl.setExecutor(executor);
-
- biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
- biDataService = biDataImpl;
- biDataImpl.setExecutor(executor);
-
- rawDataStore = new HashMapDataStore();
- schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
- schemaAwareDataStore.changeDelegate(rawDataStore);
- dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
- dataStore = dataStoreStats;
-
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
- .builder().toInstance();
- biDataImpl.registerConfigurationReader(treeRoot, dataStore);
- biDataImpl.registerOperationalReader(treeRoot, dataStore);
- biDataImpl.registerCommitHandler(treeRoot, dataStore);
-
- mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
- mappingServiceImpl.setPool(POOL);
- mappingService = mappingServiceImpl;
- File pathname = new File("target/gen-classes-debug");
- // System.out.println("Generated classes are captured in " +
- // pathname.getAbsolutePath());
- mappingServiceImpl.start(null);
- // mappingServiceImpl.getBinding().setClassFileCapturePath(pathname);
-
- connectorServiceImpl = new BindingIndependentDataServiceConnector();
- connectorServiceImpl.setBaDataService(baDataService);
- connectorServiceImpl.setBiDataService(biDataService);
- connectorServiceImpl.setMappingService(mappingServiceImpl);
- connectorServiceImpl.start();
-
- String[] yangFiles = getModelFilenames();
- if (yangFiles != null && yangFiles.length > 0) {
- SchemaContext context = getContext(yangFiles);
- mappingServiceImpl.onGlobalContextUpdated(context);
- schemaAwareDataStore.onGlobalContextUpdated(context);
- }
+ ListeningExecutorService executor = MoreExecutors.sameThreadExecutor();
+ BindingBrokerTestFactory factory = new BindingBrokerTestFactory();
+ factory.setExecutor(executor);
+ factory.setStartWithParsedSchema(getStartWithSchema());
+ testContext = factory.getTestContext();
+ testContext.start();
+
+ baDataService = testContext.getBindingDataBroker();
+ biDataService = testContext.getDomDataBroker();
+ dataStore = testContext.getDomDataStore();
+ mappingService = testContext.getBindingToDomMappingService();
}
- protected String[] getModelFilenames() {
- return getAllModelFilenames();
- }
-
- public static String[] getAllModelFilenames() {
- Predicate<String> predicate = new Predicate<String>() {
- @Override
- public boolean apply(String input) {
- return input.endsWith(".yang");
- }
- };
- Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
- Set<String> result = reflection.getResources(predicate);
- return (String[]) result.toArray(new String[result.size()]);
- }
-
- public static SchemaContext getContext(String[] yangFiles) {
-
- ClassLoader loader = AbstractDataServiceTest.class.getClassLoader();
-
- List<InputStream> streams = new ArrayList<>();
- for (String string : yangFiles) {
- InputStream stream = loader.getResourceAsStream(string);
- streams.add(stream);
-
- }
- YangParserImpl parser = new YangParserImpl();
-
- Set<Module> modules = parser.parseYangModelsFromStreams(streams);
- return parser.resolveSchemaContext(modules);
+ protected boolean getStartWithSchema() {
+ return true;
}
@After
public void afterTest() {
- log.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
- dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
- dataStoreStats.getConfigurationReadAverageTime());
-
- log.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
- dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
- dataStoreStats.getOperationalReadAverageTime());
-
- log.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
- dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
- dataStoreStats.getRequestCommitAverageTime());
+ testContext.logDataStoreStatistics();
}
}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.util;
+
+import java.util.concurrent.ExecutorService;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public class BindingBrokerTestFactory {
+
+ private static final ClassPool CLASS_POOL = new ClassPool();
+ private boolean startWithParsedSchema = true;
+ private ExecutorService executor;
+ private ClassPool classPool;
+
+
+ public boolean isStartWithParsedSchema() {
+ return startWithParsedSchema;
+ }
+
+ public void setStartWithParsedSchema(boolean startWithParsedSchema) {
+ this.startWithParsedSchema = startWithParsedSchema;
+ }
+
+ public ExecutorService getExecutor() {
+ return executor;
+ }
+
+ public void setExecutor(ExecutorService executor) {
+ this.executor = executor;
+ }
+
+
+ public BindingTestContext getTestContext() {
+ Preconditions.checkState(executor != null, "Executor is not set.");
+ ListeningExecutorService listenableExecutor = MoreExecutors.listeningDecorator(executor);
+ return new BindingTestContext(listenableExecutor, getClassPool(),startWithParsedSchema);
+ }
+
+ public ClassPool getClassPool() {
+ if(classPool == null) {
+ return CLASS_POOL;
+ }
+
+ return classPool;
+ }
+
+ public void setClassPool(ClassPool classPool) {
+ this.classPool = classPool;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.util;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.dom.serializer.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.core.api.data.DataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import static com.google.common.base.Preconditions.*;
+
+public class BindingTestContext {
+
+
+ public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+ .builder().toInstance();
+
+ private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
+
+ private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
+ private DataBrokerImpl baDataImpl;
+ private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+
+ private BindingIndependentDataServiceConnector connectorServiceImpl;
+ private HashMapDataStore rawDataStore;
+ private SchemaAwareDataStoreAdapter schemaAwareDataStore;
+ private DataStoreStatsWrapper dataStoreStats;
+ private DataStore dataStore;
+
+
+ private boolean dataStoreStatisticsEnabled = false;
+
+ private final ListeningExecutorService executor;
+ private final ClassPool classPool;
+
+ private final boolean startWithSchema;
+
+ protected BindingTestContext(ListeningExecutorService executor, ClassPool classPool, boolean startWithSchema) {
+ this.executor = executor;
+ this.classPool = classPool;
+ this.startWithSchema = startWithSchema;
+ }
+
+ public void startDomDataStore() {
+ checkState(dataStore == null, "DataStore already started.");
+ checkState(biDataImpl != null, "Dom Data Broker not present");
+ rawDataStore = new HashMapDataStore();
+ schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
+ schemaAwareDataStore.changeDelegate(rawDataStore);
+ if(dataStoreStatisticsEnabled) {
+ dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
+ dataStore = dataStoreStats;
+ } else {
+ dataStore = schemaAwareDataStore;
+ }
+
+ biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
+ biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
+ biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
+ }
+
+ public void startDomDataBroker() {
+ checkState(executor != null,"Executor needs to be set");
+ biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+ biDataImpl.setExecutor(executor);
+ }
+
+ public void startBindingDataBroker() {
+ checkState(executor != null,"Executor needs to be set");
+ baDataImpl = new DataBrokerImpl();
+ baDataImpl.setExecutor(executor);
+ }
+
+ public void startBindingToDomDataConnector() {
+ checkState(baDataImpl != null,"Binding Data Broker needs to be started");
+ checkState(biDataImpl != null,"DOM Data Broker needs to be started.");
+ checkState(mappingServiceImpl != null,"DOM Mapping Service needs to be started.");
+ connectorServiceImpl = new BindingIndependentDataServiceConnector();
+ connectorServiceImpl.setBaDataService(baDataImpl);
+ connectorServiceImpl.setBiDataService(biDataImpl);
+ connectorServiceImpl.setMappingService(mappingServiceImpl);
+ connectorServiceImpl.start();
+ }
+
+ public void startBindingToDomMappingService() {
+ checkState(classPool != null,"ClassPool needs to be present");
+ mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
+ mappingServiceImpl.setPool(classPool);
+ mappingServiceImpl.start(null);
+ }
+
+
+ public void updateYangSchema(String[] files) {
+ SchemaContext context = getContext(files);
+ if(schemaAwareDataStore != null) {
+ schemaAwareDataStore.onGlobalContextUpdated(context);
+ }
+ if(mappingServiceImpl != null) {
+ mappingServiceImpl.onGlobalContextUpdated(context);
+ }
+ }
+
+
+ public static String[] getAllYangFilesOnClasspath() {
+ Predicate<String> predicate = new Predicate<String>() {
+ @Override
+ public boolean apply(String input) {
+ return input.endsWith(".yang");
+ }
+ };
+ Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
+ Set<String> result = reflection.getResources(predicate);
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ private static SchemaContext getContext(String[] yangFiles) {
+ ClassLoader loader = BindingTestContext.class.getClassLoader();
+ List<InputStream> streams = new ArrayList<>();
+ for (String string : yangFiles) {
+ InputStream stream = loader.getResourceAsStream(string);
+ streams.add(stream);
+ }
+ YangParserImpl parser = new YangParserImpl();
+ Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+ return parser.resolveSchemaContext(modules);
+ }
+
+ public void start() {
+ startBindingDataBroker();
+ startDomDataBroker();
+ startDomDataStore();
+ startBindingToDomMappingService();
+ startBindingToDomDataConnector();
+ if(startWithSchema) {
+ loadYangSchemaFromClasspath();
+ }
+ }
+
+ public void loadYangSchemaFromClasspath() {
+ String[] files = getAllYangFilesOnClasspath();
+ updateYangSchema(files);
+ }
+
+ public DataProviderService getBindingDataBroker() {
+ return baDataImpl;
+ }
+
+ public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
+ return biDataImpl;
+ }
+
+ public DataStore getDomDataStore() {
+ return dataStore;
+ }
+
+ public BindingIndependentMappingService getBindingToDomMappingService() {
+ return mappingServiceImpl;
+ }
+
+ public void logDataStoreStatistics() {
+ if(dataStoreStats == null) {
+ return;
+ }
+
+ LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+ dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
+ dataStoreStats.getConfigurationReadAverageTime());
+
+ LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+ dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
+ dataStoreStats.getOperationalReadAverageTime());
+
+ LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
+ dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
+ dataStoreStats.getRequestCommitAverageTime());
+ }
+}
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-binding-dom-it</artifactId>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <includes>org.opendaylight.controller.*</includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>post-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
.toInstance();
private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
- @Override
- protected String[] getModelFilenames() {
- return null;
- }
-
/**
*
*
}
});
- SchemaContext ctx = getContext(getAllModelFilenames());
- schemaAwareDataStore.onGlobalContextUpdated(ctx);
- mappingServiceImpl.onGlobalContextUpdated(ctx);
+ testContext.loadYangSchemaFromClasspath();
RpcResult<TransactionStatus> result = future.get().get();
assertEquals(TransactionStatus.COMMITED, result.getResult());
return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA);
}
+
+ @Override
+ protected boolean getStartWithSchema() {
+ return false;
+ }
}
</pluginManagement>
</build>
+
<dependencies>
<dependency>
<groupId>org.opendaylight.yangtools.thirdparty</groupId>
}\r
\r
override readConfigurationData(P path) {\r
+ val local = this.updatedConfigurationData.get(path);\r
+ if(local != null) {\r
+ return local;\r
+ }\r
+ \r
return broker.readConfigurationData(path);\r
}\r
\r
override readOperationalData(P path) {\r
+ val local = this.updatedOperationalData.get(path);\r
+ if(local != null) {\r
+ return local;\r
+ }\r
return broker.readOperationalData(path);\r
}\r
\r