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.binding.impl.ForwardedBackwardsCompatibleDataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
23 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMDataBrokerImpl;
24 import org.opendaylight.controller.md.sal.dom.broker.impl.compat.BackwardsCompatibleDataBroker;
25 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
26 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
27 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
28 import org.opendaylight.controller.sal.binding.api.mount.MountProviderService;
29 import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
30 import org.opendaylight.controller.sal.binding.impl.NotificationBrokerImpl;
31 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
32 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingDomConnectorDeployer;
33 import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
34 import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBindingBrokerImpl;
35 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
36 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
37 import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
38 import org.opendaylight.controller.sal.core.api.BrokerService;
39 import org.opendaylight.controller.sal.core.api.RpcImplementation;
40 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
41 import org.opendaylight.controller.sal.core.api.RpcRegistrationListener;
42 import org.opendaylight.controller.sal.core.api.data.DataStore;
43 import org.opendaylight.controller.sal.core.api.mount.MountProvisionService;
44 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
45 import org.opendaylight.controller.sal.dom.broker.BrokerImpl;
46 import org.opendaylight.controller.sal.dom.broker.MountPointManagerImpl;
47 import org.opendaylight.controller.sal.dom.broker.impl.DataStoreStatsWrapper;
48 import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
49 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
50 import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
51 import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
52 import org.opendaylight.yangtools.concepts.ListenerRegistration;
53 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
54 import org.opendaylight.yangtools.yang.common.QName;
55 import org.opendaylight.yangtools.yang.common.RpcResult;
56 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
57 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
58 import org.opendaylight.yangtools.yang.model.api.Module;
59 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
60 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
61 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
62 import org.reflections.Reflections;
63 import org.reflections.scanners.ResourcesScanner;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 import com.google.common.base.Predicate;
68 import com.google.common.collect.ClassToInstanceMap;
69 import com.google.common.collect.ImmutableClassToInstanceMap;
70 import com.google.common.collect.ImmutableMap;
71 import com.google.common.util.concurrent.ListeningExecutorService;
73 public class BindingTestContext implements AutoCloseable, SchemaContextProvider {
75 public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
76 .builder().toInstance();
78 private static final Logger LOG = LoggerFactory.getLogger(BindingTestContext.class);
80 private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
82 private DomForwardedBindingBrokerImpl baBrokerImpl;
83 private DataBrokerImpl baDataImpl;
84 private NotificationBrokerImpl baNotifyImpl;
85 private BindingIndependentConnector baConnectImpl;
87 private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
88 private org.opendaylight.controller.sal.core.api.data.DataProviderService biDataLegacyBroker;
89 private BrokerImpl biBrokerImpl;
90 private HashMapDataStore rawDataStore;
91 private SchemaAwareDataStoreAdapter schemaAwareDataStore;
92 private DataStoreStatsWrapper dataStoreStats;
93 private DataStore dataStore;
95 private final boolean dataStoreStatisticsEnabled = false;
97 private final ListeningExecutorService executor;
98 private final ClassPool classPool;
100 private final boolean startWithSchema;
102 private MountPointManagerImpl biMountImpl;
104 private SchemaContext schemaContext;
106 private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
108 private BackwardsCompatibleDataBroker biCompatibleBroker;
110 private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
112 private DataProviderService baData;
114 private DOMDataBroker newDOMDataBroker;
117 public SchemaContext getSchemaContext() {
118 return schemaContext;
121 public DOMDataBroker getDomAsyncDataBroker() {
122 return newDOMDataBroker;
125 protected BindingTestContext(final ListeningExecutorService executor, final ClassPool classPool, final boolean startWithSchema) {
126 this.executor = executor;
127 this.classPool = classPool;
128 this.startWithSchema = startWithSchema;
131 public void startDomDataStore() {
132 checkState(dataStore == null, "DataStore already started.");
133 checkState(biDataImpl != null, "Dom Data Broker not present");
134 rawDataStore = new HashMapDataStore();
135 schemaAwareDataStore = new SchemaAwareDataStoreAdapter();
136 schemaAwareDataStore.changeDelegate(rawDataStore);
137 if (dataStoreStatisticsEnabled) {
138 dataStoreStats = new DataStoreStatsWrapper(schemaAwareDataStore);
139 dataStore = dataStoreStats;
141 dataStore = schemaAwareDataStore;
144 biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
145 biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
146 biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
149 public void startDomDataBroker() {
150 checkState(executor != null, "Executor needs to be set");
151 biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
152 biDataImpl.setExecutor(executor);
153 biDataLegacyBroker = biDataImpl;
156 public void startNewDomDataBroker() {
157 checkState(executor != null, "Executor needs to be set");
158 InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", executor);
159 InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", executor);
160 newDatastores = ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
161 .put(LogicalDatastoreType.OPERATIONAL, operStore)
162 .put(LogicalDatastoreType.CONFIGURATION, configStore)
165 newDOMDataBroker = new DOMDataBrokerImpl(newDatastores, executor);
167 biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker);
169 schemaListeners.add(configStore);
170 schemaListeners.add(operStore);
171 schemaListeners.add(biCompatibleBroker);
172 biDataLegacyBroker = biCompatibleBroker;
175 public void startBindingDataBroker() {
176 checkState(executor != null, "Executor needs to be set");
177 baDataImpl = new DataBrokerImpl();
178 baDataImpl.setExecutor(executor);
182 public void startBindingBroker() {
183 checkState(executor != null, "Executor needs to be set");
184 checkState(baData != null, "Binding Data Broker must be started");
185 checkState(baNotifyImpl != null, "Notification Service must be started");
186 baBrokerImpl = new DomForwardedBindingBrokerImpl("test");
188 baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
189 baBrokerImpl.getMountManager().setNotificationExecutor(executor);
190 baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
191 baBrokerImpl.setDataBroker(baData);
192 baBrokerImpl.setNotificationBroker(baNotifyImpl);
193 baBrokerImpl.start();
196 public void startForwarding() {
197 checkState(baData != null, "Binding Data Broker needs to be started");
198 checkState(biDataLegacyBroker != null, "DOM Data Broker needs to be started.");
199 checkState(mappingServiceImpl != null, "DOM Mapping Service needs to be started.");
201 baConnectImpl = BindingDomConnectorDeployer.createConnector(getBindingToDomMappingService());
202 baConnectImpl.setDomRpcRegistry(getDomRpcRegistry());
203 baBrokerImpl.setConnector(baConnectImpl);
204 baBrokerImpl.setDomProviderContext(createMockContext());
205 baBrokerImpl.startForwarding();
208 private ProviderSession createMockContext() {
210 final ClassToInstanceMap<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
211 .<BrokerService> builder()
213 .put(org.opendaylight.controller.sal.core.api.data.DataProviderService.class, biDataLegacyBroker) //
214 .put(RpcProvisionRegistry.class, biBrokerImpl.getRouter()) //
215 .put(MountProvisionService.class, biMountImpl) //
218 return new ProviderSession() {
221 public Future<RpcResult<CompositeNode>> rpc(final QName rpc, final CompositeNode input) {
222 throw new UnsupportedOperationException();
226 public <T extends BrokerService> T getService(final Class<T> service) {
227 return domBrokerServices.getInstance(service);
231 public boolean isClosed() {
236 public Set<QName> getSupportedRpcs() {
241 public void close() {
245 public ListenerRegistration<RpcRegistrationListener> addRpcRegistrationListener(
246 final RpcRegistrationListener listener) {
251 public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation)
252 throws IllegalArgumentException {
257 public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
262 public RoutedRpcRegistration addMountedRpcImplementation(final QName rpcType, final RpcImplementation implementation) {
268 public void startBindingToDomMappingService() {
269 checkState(classPool != null, "ClassPool needs to be present");
270 mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
271 mappingServiceImpl.setPool(classPool);
272 mappingServiceImpl.init();
275 public void updateYangSchema(final String[] files) {
276 schemaContext = getContext(files);
278 if (schemaAwareDataStore != null) {
279 schemaAwareDataStore.onGlobalContextUpdated(schemaContext);
281 if (mappingServiceImpl != null) {
282 mappingServiceImpl.onGlobalContextUpdated(schemaContext);
284 for(SchemaContextListener listener : schemaListeners) {
285 listener.onGlobalContextUpdated(schemaContext);
289 public static String[] getAllYangFilesOnClasspath() {
290 Predicate<String> predicate = new Predicate<String>() {
292 public boolean apply(final String input) {
293 return input.endsWith(".yang");
296 Reflections reflection = new Reflections("META-INF.yang", new ResourcesScanner());
297 Set<String> result = reflection.getResources(predicate);
298 return result.toArray(new String[result.size()]);
301 private static SchemaContext getContext(final String[] yangFiles) {
302 ClassLoader loader = BindingTestContext.class.getClassLoader();
303 List<InputStream> streams = new ArrayList<>();
304 for (String string : yangFiles) {
305 InputStream stream = loader.getResourceAsStream(string);
308 YangParserImpl parser = new YangParserImpl();
309 Set<Module> modules = parser.parseYangModelsFromStreams(streams);
310 return parser.resolveSchemaContext(modules);
313 public void startLegacy() {
314 startBindingDataBroker();
315 startBindingNotificationBroker();
316 startBindingBroker();
317 startDomDataBroker();
320 startDomMountPoint();
321 startBindingToDomMappingService();
323 if (startWithSchema) {
324 loadYangSchemaFromClasspath();
328 public void start() {
329 startNewDomDataBroker();
331 startDomMountPoint();
332 startBindingToDomMappingService();
333 startNewBindingDataBroker();
335 startBindingNotificationBroker();
336 startBindingBroker();
339 if (startWithSchema) {
340 loadYangSchemaFromClasspath();
344 public void startNewBindingDataBroker() {
345 ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor);
346 schemaListeners.add(forwarded);
350 private void startDomMountPoint() {
351 biMountImpl = new MountPointManagerImpl();
352 biMountImpl.setDataBroker(getDomDataBroker());
355 private void startDomBroker() {
356 checkState(executor != null);
357 biBrokerImpl = new BrokerImpl();
358 biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", this));
362 public void startBindingNotificationBroker() {
363 checkState(executor != null);
364 baNotifyImpl = new NotificationBrokerImpl(executor);
368 public void loadYangSchemaFromClasspath() {
369 String[] files = getAllYangFilesOnClasspath();
370 updateYangSchema(files);
373 public DataProviderService getBindingDataBroker() {
377 public org.opendaylight.controller.sal.core.api.data.DataProviderService getDomDataBroker() {
378 return biDataLegacyBroker;
381 public DataStore getDomDataStore() {
385 public BindingIndependentMappingService getBindingToDomMappingService() {
386 return mappingServiceImpl;
389 public void logDataStoreStatistics() {
390 if (dataStoreStats == null) {
394 LOG.info("BIDataStore Statistics: Configuration Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
395 dataStoreStats.getConfigurationReadCount(), dataStoreStats.getConfigurationReadTotalTime(),
396 dataStoreStats.getConfigurationReadAverageTime());
398 LOG.info("BIDataStore Statistics: Operational Read Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
399 dataStoreStats.getOperationalReadCount(), dataStoreStats.getOperationalReadTotalTime(),
400 dataStoreStats.getOperationalReadAverageTime());
402 LOG.info("BIDataStore Statistics: Request Commit Count: {} TotalTime: {} ms AverageTime (ns): {} ms",
403 dataStoreStats.getRequestCommitCount(), dataStoreStats.getRequestCommitTotalTime(),
404 dataStoreStats.getRequestCommitAverageTime());
407 public RpcProviderRegistry getBindingRpcRegistry() {
408 return baBrokerImpl.getRoot();
411 public RpcProvisionRegistry getDomRpcRegistry() {
412 if (biBrokerImpl == null) {
415 return biBrokerImpl.getRouter();
418 public RpcImplementation getDomRpcInvoker() {
419 return biBrokerImpl.getRouter();
423 public void close() throws Exception {
427 public MountProviderService getBindingMountProviderService() {
428 return baBrokerImpl.getMountManager();
431 public MountProvisionService getDomMountProviderService() {