2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.binding.test.util;
10 import static com.google.common.base.Preconditions.checkState;
12 import java.io.InputStream;
13 import java.util.ArrayList;
14 import java.util.List;
16 import java.util.concurrent.Future;
18 import javassist.ClassPool;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
22 import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
23 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
24 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
25 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
26 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
27 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
28 import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
29 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
30 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
31 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
32 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;
33 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
34 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
35 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
36 import org.opendaylight.controller.sal.core.api.BrokerService;
37 import org.opendaylight.controller.sal.core.api.RpcImplementation;
38 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
39 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
40 import org.opendaylight.controller.sal.core.api.data.DataStore;
41 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
42 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
43 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
44 import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
45 import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
46 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
47 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
48 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
49 import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
50 import org.opendaylight.yangtools.concepts.ListenerRegistration;
51 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
52 import org.opendaylight.yangtools.yang.common.QName;
53 import org.opendaylight.yangtools.yang.common.RpcResult;
54 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
55 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
56 import org.opendaylight.yangtools.yang.model.api.Module;
57 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
58 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
59 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
60 import org.reflections.Reflections;
61 import org.reflections.scanners.ResourcesScanner;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
65 import com.google.common.base.Predicate;
66 import com.google.common.collect.ClassToInstanceMap;
67 import com.google.common.collect.ImmutableClassToInstanceMap;
68 import com.google.common.collect.ImmutableMap;
69 import com.google.common.util.concurrent.ListeningExecutorService;
71 public class BindingTestContext implements AutoCloseable, SchemaContextProvider {
73 public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
74 .builder().toInstance();
76 private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
78 private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
80 private DomForwardedBindingBrokerImpl baBrokerImpl;
81 private DataBrokerImpl baDataImpl;
82 private NotificationBrokerImpl baNotifyImpl;
83 private BindingIndependentConnector baConnectImpl;
85 private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
86 private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataLegacyBroker;
87 private BrokerImpl biBrokerImpl;
88 private HashMapDataStore rawDataStore;
89 private SchemaAwareDataStoreAdapter schemaAwareDataStore;
90 private DataStoreStatsWrapper dataStoreStats;
91 private DataStore dataStore;
93 private final boolean dataStoreStatisticsEnabled = false;
95 private final ListeningExecutorService executor;
96 private final ClassPool classPool;
98 private final boolean startWithSchema;
100 private MountPointManagerImpl biMountImpl;
102 private SchemaContext schemaContext;
104 private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
106 private BackwardsCompatibleDataBroker biCompatibleBroker;
108 private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
111 public SchemaContext getSchemaContext() {
112 return schemaContext;
115 protected BindingTestContext(final ListeningExecutorService executor, final ClassPool classPool, final boolean startWithSchema) {
116 this.executor = executor;
117 this.classPool = classPool;
118 this.startWithSchema = startWithSchema;
121 public void startDomDataStore() {
122 checkState(dataStore == null, "DataStore already started.");
123 checkState(biDataImpl != null, "Dom Data Broker not present");
124 rawDataStore = new HashMapDataStore();
125 schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
126 schemaAwareDataStore.changeDelegate(rawDataStore);
127 if (dataStoreStatisticsEnabled) {
128 dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
129 dataStore = dataStoreStats;
131 dataStore = schemaAwareDataStore;
134 biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
135 biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
136 biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
139 public void startDomDataBroker() {
140 checkState(executor != null, "Executor needs to be set");
141 biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
142 biDataImpl.setExecutor(executor);
143 biDataLegacyBroker = biDataImpl;
146 public void startNewDomDataBroker() {
147 checkState(executor != null, "Executor needs to be set");
148 InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", executor);
149 InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", executor);
150 newDatastores = ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
151 .put(LogicalDatastoreType.OPERATIONAL, operStore)
152 .put(LogicalDatastoreType.CONFIGURATION, configStore)
155 DOMDataBrokerImpl newBiDataImpl = new DOMDataBrokerImpl(newDatastores, executor);
157 biCompatibleBroker = new BackwardsCompatibleDataBroker(newBiDataImpl);
159 schemaListeners.add(configStore);
160 schemaListeners.add(operStore);
161 schemaListeners.add(biCompatibleBroker);
162 biDataLegacyBroker = biCompatibleBroker;
165 public void startBindingDataBroker() {
166 checkState(executor != null, "Executor needs to be set");
167 baDataImpl = new DataBrokerImpl();
168 baDataImpl.setExecutor(executor);
171 public void startBindingBroker() {
172 checkState(executor != null, "Executor needs to be set");
173 checkState(baDataImpl != null, "Binding Data Broker must be started");
174 checkState(baNotifyImpl != null, "Notification Service must be started");
175 baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
177 baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
178 baBrokerImpl.getMountManager().setNotificationExecutor(executor);
179 baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
180 baBrokerImpl.setDataBroker(baDataImpl);
181 baBrokerImpl.setNotificationBroker(baNotifyImpl);
182 baBrokerImpl.start();
185 public void startForwarding() {
186 checkState(baDataImpl != null, "Binding Data Broker needs to be started");
187 checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
188 checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
190 baConnectImpl = BindingDomConnectorDeployer.createConnector(getBindingToDomMappingService());
191 baConnectImpl.setDomRpcRegistry(getDomRpcRegistry());
192 baBrokerImpl.setConnector(baConnectImpl);
193 baBrokerImpl.setDomProviderContext(createMockContext());
194 baBrokerImpl.startForwarding();
197 private ProviderSession createMockContext() {
199 final ClassToInstanceMap<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
200 .<BrokerService> builder()
202 .put(org.opendaylight.controller.sal.core.api.data.DataProviderService.class, biDataLegacyBroker) //
203 .put(RpcProvisionRegistry.class, biBrokerImpl.getRouter()) //
204 .put(MountProvisionService.class, biMountImpl) //
207 return new ProviderSession() {
210 public Future<RpcResult<CompositeNode>> rpc(final QName rpc, final CompositeNode input) {
211 throw new UnsupportedOperationException();
215 public <T extends BrokerService> T getService(final Class<T> service) {
216 return domBrokerServices.getInstance(service);
220 public boolean isClosed() {
225 public Set<QName> getSupportedRpcs() {
230 public void close() {
234 public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
235 final RpcRegistrationListener listener) {
240 public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
241 throws IllegalArgumentException {
246 public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
251 public RoutedRpcRegistration addMountedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
257 public void startBindingToDomMappingService() {
258 checkState(classPool != null, "ClassPool needs to be present");
259 mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
260 mappingServiceImpl.setPool(classPool);
261 mappingServiceImpl.init();
264 public void updateYangSchema(final String[] files) {
265 schemaContext = getContext(files);
267 if (schemaAwareDataStore != null) {
268 schemaAwareDataStore.onGlobalContextUpdated(schemaContext);
270 if (mappingServiceImpl != null) {
271 mappingServiceImpl.onGlobalContextUpdated(schemaContext);
273 for(SchemaContextListener listener : schemaListeners) {
274 listener.onGlobalContextUpdated(schemaContext);
278 public static String[] getAllYangFilesOnClasspath() {
279 Predicate<String> predicate = new Predicate<String>() {
281 public boolean apply(final String input) {
282 return input.endsWith(".yang");
285 Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
286 Set<String> result = reflection.getResources(predicate);
287 return result.toArray(new String[result.size()]);
290 private static SchemaContext getContext(final String[] yangFiles) {
291 ClassLoader loader = BindingTestContext.class.getClassLoader();
292 List<InputStream> streams = new ArrayList<>();
293 for (String string : yangFiles) {
294 InputStream stream = loader.getResourceAsStream(string);
297 YangParserImpl parser = new YangParserImpl();
298 Set<Module> modules = parser.parseYangModelsFromStreams(streams);
299 return parser.resolveSchemaContext(modules);
302 public void startLegacy() {
303 startBindingDataBroker();
304 startBindingNotificationBroker();
305 startBindingBroker();
306 startDomDataBroker();
309 startDomMountPoint();
310 startBindingToDomMappingService();
312 if (startWithSchema) {
313 loadYangSchemaFromClasspath();
317 public void start() {
318 startBindingDataBroker();
319 startBindingNotificationBroker();
320 startBindingBroker();
321 startNewDomDataBroker();
323 startDomMountPoint();
324 startBindingToDomMappingService();
326 if (startWithSchema) {
327 loadYangSchemaFromClasspath();
331 private void startDomMountPoint() {
332 biMountImpl = new MountPointManagerImpl();
333 biMountImpl.setDataBroker(getDomDataBroker());
336 private void startDomBroker() {
337 checkState(executor != null);
338 biBrokerImpl = new BrokerImpl();
339 biBrokerImpl.setExecutor(executor);
340 biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", this));
344 public void startBindingNotificationBroker() {
345 checkState(executor != null);
346 baNotifyImpl = new NotificationBrokerImpl(executor);
350 public void loadYangSchemaFromClasspath() {
351 String[] files = getAllYangFilesOnClasspath();
352 updateYangSchema(files);
355 public DataProviderService getBindingDataBroker() {
359 public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
360 return biDataLegacyBroker;
363 public DataStore getDomDataStore() {
367 public BindingIndependentMappingService getBindingToDomMappingService() {
368 return mappingServiceImpl;
371 public void logDataStoreStatistics() {
372 if (dataStoreStats == null) {
376 LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
377 dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
378 dataStoreStats.getConfigurationReadAverageTime());
380 LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
381 dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
382 dataStoreStats.getOperationalReadAverageTime());
384 LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
385 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
386 dataStoreStats.getRequestCommitAverageTime());
389 public RpcProviderRegistry getBindingRpcRegistry() {
390 return baBrokerImpl.getRoot();
393 public RpcProvisionRegistry getDomRpcRegistry() {
394 if (biBrokerImpl == null) {
397 return biBrokerImpl.getRouter();
400 public RpcImplementation getDomRpcInvoker() {
401 return biBrokerImpl.getRouter();
405 public void close() throws Exception {
409 public MountProviderService getBindingMountProviderService() {
410 return baBrokerImpl.getMountManager();
413 public MountProvisionService getDomMountProviderService() {