Add binding adapter components for data services 86/91786/4
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 30 Jul 2020 21:59:36 +0000 (23:59 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 30 Jul 2020 22:16:07 +0000 (00:16 +0200)
Rather than operating on service registry directly, create binding
adapters as dedicated components. This allows proper provides/requires
validation for downstream component users.

JIRA: MDSAL-587
Change-Id: I5c9c8140660ac5c7d7a82c25bcbf4e26fc8716be
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptingTracker.java [deleted file]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AdaptingComponentTracker.java [deleted file]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AdaptingTracker.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/Dict.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/DynamicBindingAdapter.java
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataBroker.java [new file with mode: 0644]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataTreeService.java [new file with mode: 0644]

diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptingTracker.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptingTracker.java
deleted file mode 100644 (file)
index bfd368d..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.mdsal.binding.dom.adapter.osgi;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.function.Function;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.api.BindingService;
-import org.opendaylight.mdsal.dom.api.DOMService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A ServiceTracker which adapts a DOMService to a BindingService.
- *
- * @param <D> DOMService type
- * @param <B> BindingService type
- * @author Robert Varga
- */
-abstract class AbstractAdaptingTracker<D extends DOMService, B extends BindingService, T>
-        extends ServiceTracker<D, T> {
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractAdaptingTracker.class);
-
-    private final Function<D, B> bindingFactory;
-    final @NonNull Class<B> bindingClass;
-
-    AbstractAdaptingTracker(final BundleContext ctx, final Class<D> domClass, final Class<B> bindingClass,
-        final Function<D, B> bindingFactory) {
-        super(ctx, domClass, null);
-        this.bindingClass = requireNonNull(bindingClass);
-        this.bindingFactory = requireNonNull(bindingFactory);
-    }
-
-    @Override
-    public final void open(final boolean trackAllServices) {
-        LOG.debug("Starting tracker for {}", bindingClass.getName());
-        super.open(trackAllServices);
-        LOG.debug("Tracker for {} started", bindingClass.getName());
-    }
-
-    @Override
-    public final T addingService(final ServiceReference<D> reference) {
-        if (reference == null) {
-            LOG.debug("Null reference for {}, ignoring it", bindingClass.getName());
-            return null;
-        }
-        if (reference.getProperty(ServiceProperties.IGNORE_PROP) != null) {
-            LOG.debug("Ignoring reference {} due to {}", reference, ServiceProperties.IGNORE_PROP);
-            return null;
-        }
-
-        final D dom = context.getService(reference);
-        if (dom == null) {
-            LOG.debug("Could not get {} service from {}, ignoring it", bindingClass.getName(), reference);
-            return null;
-        }
-
-        return addingService(reference, dom, bindingFactory.apply(dom));
-    }
-
-    abstract @NonNull T addingService(@NonNull ServiceReference<D> reference, @NonNull D dom, @NonNull B binding);
-
-    @Override
-    public final void modifiedService(final ServiceReference<D> reference, final T service) {
-        if (service != null && reference != null) {
-            updatedService(reference, service);
-        }
-    }
-
-    abstract void updatedService(@NonNull ServiceReference<D> reference, @NonNull T service);
-
-    @Override
-    public final void removedService(final ServiceReference<D> reference, final T service) {
-        if (service != null) {
-            context.ungetService(reference);
-            removedService(service);
-            LOG.debug("Unregistered service {}", service);
-        }
-    }
-
-    abstract void removedService(@NonNull T service);
-
-}
diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AdaptingComponentTracker.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AdaptingComponentTracker.java
deleted file mode 100644 (file)
index 86a8c09..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.mdsal.binding.dom.adapter.osgi;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.function.Function;
-import org.opendaylight.mdsal.binding.api.BindingService;
-import org.opendaylight.mdsal.dom.api.DOMService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.component.ComponentFactory;
-import org.osgi.service.component.ComponentInstance;
-
-final class AdaptingComponentTracker<D extends DOMService, B extends BindingService>
-        extends AbstractAdaptingTracker<D, B, AdaptingComponentTracker.ComponentHolder<B>> {
-    static final class ComponentHolder<B extends BindingService> {
-        final B binding;
-        ComponentInstance component;
-
-        ComponentHolder(final B binding, final ComponentInstance component) {
-            this.binding = requireNonNull(binding);
-            this.component = requireNonNull(component);
-        }
-    }
-
-    private final ComponentFactory componentFactory;
-
-    AdaptingComponentTracker(final BundleContext ctx, final Class<D> domClass, final Class<B> bindingClass,
-            final Function<D, B> bindingFactory, final ComponentFactory componentFactory) {
-        super(ctx, domClass, bindingClass, bindingFactory);
-        this.componentFactory = requireNonNull(componentFactory);
-    }
-
-    @Override
-    ComponentHolder<B> addingService(final ServiceReference<D> reference, final D dom, final B binding) {
-        return new ComponentHolder<>(binding, componentFactory.newInstance(Dict.fromReference(reference, binding)));
-    }
-
-    @Override
-    void removedService(final ComponentHolder<B> service) {
-        service.component.dispose();
-    }
-
-    @Override
-    void updatedService(final ServiceReference<D> reference, final ComponentHolder<B> service) {
-        service.component.dispose();
-        service.component = componentFactory.newInstance(Dict.fromReference(reference, service.binding));
-    }
-}
index 5047134f689cd33fa141982dda3769e8f413f0a9..2413ca9e832ee0d4f9cfa4e53b3ee33b64275304 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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,
@@ -7,12 +7,17 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter.osgi;
 
+import static java.util.Objects.requireNonNull;
+
 import java.util.function.Function;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.BindingService;
 import org.opendaylight.mdsal.dom.api.DOMService;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -24,31 +29,73 @@ import org.slf4j.LoggerFactory;
  * @author Robert Varga
  */
 final class AdaptingTracker<D extends DOMService, B extends BindingService>
-        extends AbstractAdaptingTracker<D, B, ServiceRegistration<B>> {
+        extends ServiceTracker<D, AdaptingTracker.ComponentHolder<B>> {
+    static final class ComponentHolder<B extends BindingService> {
+        final B binding;
+        ComponentInstance component;
+
+        ComponentHolder(final B binding, final ComponentInstance component) {
+            this.binding = requireNonNull(binding);
+            this.component = requireNonNull(component);
+        }
+    }
+
     private static final Logger LOG = LoggerFactory.getLogger(AdaptingTracker.class);
 
+    private final Function<D, B> bindingFactory;
+    private final @NonNull Class<B> bindingClass;
+    private final ComponentFactory componentFactory;
+
     AdaptingTracker(final BundleContext ctx, final Class<D> domClass, final Class<B> bindingClass,
-            final Function<D, B> bindingFactory) {
-        super(ctx, domClass, bindingClass, bindingFactory);
+            final Function<D, B> bindingFactory, final ComponentFactory componentFactory) {
+        super(ctx, domClass, null);
+        this.bindingClass = requireNonNull(bindingClass);
+        this.bindingFactory = requireNonNull(bindingFactory);
+        this.componentFactory = requireNonNull(componentFactory);
     }
 
     @Override
-    ServiceRegistration<B> addingService(final ServiceReference<D> reference, final D dom, final B binding) {
-        final Dict props = Dict.fromReference(reference);
-        final ServiceRegistration<B> reg = context.registerService(bindingClass, binding, props);
-        LOG.debug("Registered {} adapter {} of {} with {} as {}", bindingClass.getName(), binding, dom, props, reg);
-        return reg;
+    public void open(final boolean trackAllServices) {
+        LOG.debug("Starting tracker for {}", bindingClass.getName());
+        super.open(trackAllServices);
+        LOG.debug("Tracker for {} started", bindingClass.getName());
+    }
+
+    @Override
+    public ComponentHolder<B> addingService(final ServiceReference<D> reference) {
+        if (reference == null) {
+            LOG.debug("Null reference for {}, ignoring it", bindingClass.getName());
+            return null;
+        }
+        if (reference.getProperty(ServiceProperties.IGNORE_PROP) != null) {
+            LOG.debug("Ignoring reference {} due to {}", reference, ServiceProperties.IGNORE_PROP);
+            return null;
+        }
+
+        final D dom = context.getService(reference);
+        if (dom == null) {
+            LOG.debug("Could not get {} service from {}, ignoring it", bindingClass.getName(), reference);
+            return null;
+        }
+
+        final B binding = bindingFactory.apply(dom);
+        return new ComponentHolder<>(binding, componentFactory.newInstance(Dict.fromReference(reference, binding)));
     }
 
     @Override
-    void removedService(final ServiceRegistration<B> service) {
-        service.unregister();
+    public void modifiedService(final ServiceReference<D> reference, final ComponentHolder<B> service) {
+        if (service != null && reference != null) {
+            service.component.dispose();
+            service.component = componentFactory.newInstance(Dict.fromReference(reference, service.binding));
+        }
     }
 
     @Override
-    void updatedService(final ServiceReference<D> reference, final ServiceRegistration<B> service) {
-        final Dict newProps = Dict.fromReference(reference);
-        LOG.debug("Updating service {} with properties {}", service, newProps);
-        service.setProperties(newProps);
+    public void removedService(final ServiceReference<D> reference, final ComponentHolder<B> service) {
+        if (service != null) {
+            context.ungetService(reference);
+            service.component.dispose();
+            LOG.debug("Unregistered service {}", service);
+        }
     }
 }
index d30f5ffc24686fcf2b51eb23f4c9bbbc78919c47..09a1ef7c934bb663f7cbfda2669a92e1b55859b9 100644 (file)
@@ -23,7 +23,6 @@ import org.slf4j.LoggerFactory;
 @NonNullByDefault
 final class Dict extends Dictionary<String, Object> {
     private static final Logger LOG = LoggerFactory.getLogger(Dict.class);
-    private static final Dict EMPTY = new Dict(ImmutableMap.of());
 
     private final Map<String, Object> map;
 
@@ -31,24 +30,9 @@ final class Dict extends Dictionary<String, Object> {
         this.map = ImmutableMap.copyOf(map);
     }
 
-    static Dict fromReference(final ServiceReference<?> ref) {
-        final String[] keys = ref.getPropertyKeys();
-        if (keys.length == 0) {
-            return EMPTY;
-        }
-
-        return new Dict(populateProperties(ref, keys, 0));
-    }
-
     static Dict fromReference(final ServiceReference<?> ref, final BindingService service) {
-        final Map<String, Object> props = populateProperties(ref, ref.getPropertyKeys(), 1);
-        props.put(AbstractAdaptedService.DELEGATE, service);
-        return new Dict(props);
-    }
-
-    private static Map<String, Object> populateProperties(final ServiceReference<?> ref, final String[] keys,
-            final int extra) {
-        final Map<String, Object> props = Maps.newHashMapWithExpectedSize(keys.length + extra);
+        final String[] keys = ref.getPropertyKeys();
+        final Map<String, Object> props = Maps.newHashMapWithExpectedSize(keys.length + 1);
         for (String key : keys) {
             // Ignore properties with our prefix: we are not exporting those
             if (!key.startsWith(ServiceProperties.PREFIX)) {
@@ -73,7 +57,8 @@ final class Dict extends Dictionary<String, Object> {
             }
         }
 
-        return props;
+        props.put(AbstractAdaptedService.DELEGATE, service);
+        return new Dict(props);
     }
 
     @Override
index dace2cd5c52c89083739b232bfc465d59b4be143..5cc9bdb36f798e0f80a81edfc8c00a66285d38c8 100644 (file)
@@ -50,7 +50,7 @@ import org.slf4j.LoggerFactory;
 public final class DynamicBindingAdapter {
     private static final Logger LOG = LoggerFactory.getLogger(DynamicBindingAdapter.class);
 
-    private List<AbstractAdaptingTracker<?, ?, ?>> trackers = ImmutableList.of();
+    private List<AdaptingTracker<?, ?>> trackers = ImmutableList.of();
 
     @Reference
     AdapterFactory factory = null;
@@ -58,6 +58,10 @@ public final class DynamicBindingAdapter {
     ComponentFactory actionServiceFactory = null;
     @Reference(target = "(component.factory=" + OSGiActionProviderService.FACTORY_NAME + ")")
     ComponentFactory actionProviderServiceFactory = null;
+    @Reference(target = "(component.factory=" + OSGiDataBroker.FACTORY_NAME + ")")
+    ComponentFactory dataBrokerFactory = null;
+    @Reference(target = "(component.factory=" + OSGiDataTreeService.FACTORY_NAME + ")")
+    ComponentFactory dataTreeServiceFactory = null;
     @Reference(target = "(component.factory=" + OSGiMountPointService.FACTORY_NAME + ")")
     ComponentFactory mountPointServiceFactory = null;
     @Reference(target = "(component.factory=" + OSGiNotificationService.FACTORY_NAME + ")")
@@ -72,22 +76,24 @@ public final class DynamicBindingAdapter {
     @Activate
     void activate(final BundleContext ctx) {
         trackers = ImmutableList.of(
-            new AdaptingTracker<>(ctx, DOMDataBroker.class, DataBroker.class, factory::createDataBroker),
-            new AdaptingTracker<>(ctx, DOMDataTreeService.class, DataTreeService.class, factory::createDataTreeService),
-            new AdaptingComponentTracker<>(ctx, DOMMountPointService.class, MountPointService.class,
+            new AdaptingTracker<>(ctx, DOMDataBroker.class, DataBroker.class, factory::createDataBroker,
+                    dataBrokerFactory),
+            new AdaptingTracker<>(ctx, DOMDataTreeService.class, DataTreeService.class, factory::createDataTreeService,
+                    dataTreeServiceFactory),
+            new AdaptingTracker<>(ctx, DOMMountPointService.class, MountPointService.class,
                     factory::createMountPointService, mountPointServiceFactory),
-            new AdaptingComponentTracker<>(ctx, DOMNotificationService.class, NotificationService.class,
+            new AdaptingTracker<>(ctx, DOMNotificationService.class, NotificationService.class,
                     factory::createNotificationService, notificationServiceFactory),
-            new AdaptingComponentTracker<>(ctx, DOMNotificationPublishService.class, NotificationPublishService.class,
+            new AdaptingTracker<>(ctx, DOMNotificationPublishService.class, NotificationPublishService.class,
                     factory::createNotificationPublishService, notificationPublishServiceFactory),
-            new AdaptingComponentTracker<>(ctx, DOMRpcService.class, RpcConsumerRegistry.class,
+            new AdaptingTracker<>(ctx, DOMRpcService.class, RpcConsumerRegistry.class,
                     factory::createRpcConsumerRegistry, rpcConsumerRegistryFactory),
-            new AdaptingComponentTracker<>(ctx, DOMRpcProviderService.class, RpcProviderService.class,
+            new AdaptingTracker<>(ctx, DOMRpcProviderService.class, RpcProviderService.class,
                     factory::createRpcProviderService, rpcProviderServiceFactory),
-            new AdaptingComponentTracker<>(ctx, DOMActionService.class, ActionService.class,
-                    factory::createActionService, actionServiceFactory),
-            new AdaptingComponentTracker<>(ctx, DOMActionProviderService.class, ActionProviderService.class,
-                factory::createActionProviderService, actionProviderServiceFactory));
+            new AdaptingTracker<>(ctx, DOMActionService.class, ActionService.class, factory::createActionService,
+                    actionServiceFactory),
+            new AdaptingTracker<>(ctx, DOMActionProviderService.class, ActionProviderService.class,
+                    factory::createActionProviderService, actionProviderServiceFactory));
 
         LOG.debug("Starting {} DOMService trackers", trackers.size());
         trackers.forEach(ServiceTracker::open);
@@ -98,7 +104,7 @@ public final class DynamicBindingAdapter {
     void deactivate() {
         LOG.debug("Stopping {} DOMService trackers", trackers.size());
         if (!trackers.isEmpty()) {
-            trackers.forEach(AbstractAdaptingTracker::close);
+            trackers.forEach(AdaptingTracker::close);
             LOG.info("{} DOMService trackers stopped", trackers.size());
         }
         trackers = ImmutableList.of();
diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataBroker.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataBroker.java
new file mode 100644 (file)
index 0000000..3f9ebce
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.mdsal.binding.dom.adapter.osgi;
+
+import com.google.common.annotations.Beta;
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.ReadTransaction;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.binding.api.TransactionChain;
+import org.opendaylight.mdsal.binding.api.TransactionChainListener;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+@Beta
+@Component(factory = OSGiDataBroker.FACTORY_NAME)
+public final class OSGiDataBroker extends AbstractAdaptedService<DataBroker> implements DataBroker {
+    // OSGi DS Component Factory name
+    static final String FACTORY_NAME = "org.opendaylight.mdsal.binding.dom.adapter.osgi.OSGiDataBroker";
+
+    public OSGiDataBroker() {
+        super(DataBroker.class);
+    }
+
+    @Override
+    public ReadTransaction newReadOnlyTransaction() {
+        return delegate().newReadOnlyTransaction();
+    }
+
+    @Override
+    public ReadWriteTransaction newReadWriteTransaction() {
+        return delegate().newReadWriteTransaction();
+    }
+
+    @Override
+    public WriteTransaction newWriteOnlyTransaction() {
+        return delegate().newWriteOnlyTransaction();
+    }
+
+    @Override
+    public <T extends DataObject, L extends DataTreeChangeListener<T>>
+            ListenerRegistration<L> registerDataTreeChangeListener(final DataTreeIdentifier<T> treeId,
+                    final L listener) {
+        return delegate().registerDataTreeChangeListener(treeId, listener);
+    }
+
+    @Override
+    public TransactionChain createTransactionChain(@NonNull final TransactionChainListener listener) {
+        return delegate().createTransactionChain(listener);
+    }
+
+    @Override
+    public TransactionChain createMergingTransactionChain(final TransactionChainListener listener) {
+        return delegate().createMergingTransactionChain(listener);
+    }
+
+    @Activate
+    void activate(final Map<String, ?> properties) {
+        start(properties);
+    }
+
+    @Deactivate
+    void deactivate() {
+        stop();
+    }
+}
diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataTreeService.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiDataTreeService.java
new file mode 100644 (file)
index 0000000..9210fd4
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.mdsal.binding.dom.adapter.osgi;
+
+import com.google.common.annotations.Beta;
+import java.util.Collection;
+import java.util.Map;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.DataTreeListener;
+import org.opendaylight.mdsal.binding.api.DataTreeLoopException;
+import org.opendaylight.mdsal.binding.api.DataTreeProducer;
+import org.opendaylight.mdsal.binding.api.DataTreeService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+@Beta
+@Component(factory = OSGiDataTreeService.FACTORY_NAME)
+public final class OSGiDataTreeService extends AbstractAdaptedService<DataTreeService> implements DataTreeService {
+    // OSGi DS Component Factory name
+    static final String FACTORY_NAME = "org.opendaylight.mdsal.binding.dom.adapter.osgi.OSGiDataTreeService";
+
+    public OSGiDataTreeService() {
+        super(DataTreeService.class);
+    }
+
+    @Override
+    public DataTreeProducer createProducer(final Collection<DataTreeIdentifier<?>> subtrees) {
+        return delegate().createProducer(subtrees);
+    }
+
+    @Override
+    public <T extends DataTreeListener> ListenerRegistration<T> registerListener(final T listener,
+            final Collection<DataTreeIdentifier<?>> subtrees, final boolean allowRxMerges,
+            final Collection<DataTreeProducer> producers) throws DataTreeLoopException {
+        return delegate().registerListener(listener, subtrees, allowRxMerges, producers);
+    }
+
+    @Activate
+    void activate(final Map<String, ?> properties) {
+        start(properties);
+    }
+
+    @Deactivate
+    void deactivate() {
+        stop();
+    }
+}