Add binding adapter components for RPC services 89/91789/1
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 30 Jul 2020 20:10:35 +0000 (22:10 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 31 Jul 2020 08:52:09 +0000 (10:52 +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-583
Change-Id: If9680d2efe64535551b0c7a3df8058dac89375cf
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit 5df23371ec7909983d59c278cfd28ecff66aad78)

binding/mdsal-binding-dom-adapter/pom.xml
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptedService.java [new file with mode: 0644]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptingTracker.java [new file with mode: 0644]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AdaptingComponentTracker.java [new file with mode: 0644]
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/OSGiRpcConsumerRegistry.java [new file with mode: 0644]
binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiRpcProviderService.java [new file with mode: 0644]

index 83e274c81990b8e4bf644a24bba85c938bf663a2..a8f73ad7ff4ed9e2b1078bc31e98c974eff3df81 100644 (file)
 
     <build>
         <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <Automatic-Module-Name>org.opendaylight.mdsal.binding.dom.adapter</Automatic-Module-Name>
+                    <instructions>
+                        <!-- Karaf cannot handle Factory Component requirements, see https://issues.apache.org/jira/browse/KARAF-6625 -->
+                        <_dsannotations-options>norequirements</_dsannotations-options>
+                    </instructions>
+                </configuration>
+            </plugin>
             <plugin>
                 <artifactId>maven-jar-plugin</artifactId>
                 <executions>
diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptedService.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/AbstractAdaptedService.java
new file mode 100644 (file)
index 0000000..385af93
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import java.util.Map;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.api.BindingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractAdaptedService<B extends BindingService> {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractAdaptedService.class);
+    static final @NonNull String DELEGATE =
+            "org.opendaylight.mdsal.binding.dom.adapter.osgi.AbstractAdaptedService.DELEGATE";
+
+    private final Class<B> bindingService;
+
+    private @Nullable B delegate;
+
+    AbstractAdaptedService(final Class<B> bindingService) {
+        this.bindingService = requireNonNull(bindingService);
+    }
+
+    final void start(final Map<String, ?> properties) {
+        delegate = bindingService.cast(verifyNotNull(properties.get(DELEGATE)));
+        LOG.info("Binding/DOM adapter for {} activated", bindingService.getSimpleName());
+    }
+
+    final void stop() {
+        delegate = null;
+        LOG.info("Binding/DOM adapter for {} deactivated", bindingService.getSimpleName());
+    }
+
+    final @NonNull B delegate() {
+        return verifyNotNull(delegate);
+    }
+}
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
new file mode 100644 (file)
index 0000000..bfd368d
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..86a8c09
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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 1858c2e0eaea1a02481196f429de3d8ff64ac9ab..5047134f689cd33fa141982dda3769e8f413f0a9 100644 (file)
@@ -7,15 +7,12 @@
  */
 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.framework.ServiceRegistration;
-import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -27,43 +24,16 @@ import org.slf4j.LoggerFactory;
  * @author Robert Varga
  */
 final class AdaptingTracker<D extends DOMService, B extends BindingService>
-        extends ServiceTracker<D, ServiceRegistration<B>> {
+        extends AbstractAdaptingTracker<D, B, ServiceRegistration<B>> {
     private static final Logger LOG = LoggerFactory.getLogger(AdaptingTracker.class);
 
-    private final Function<D, B> bindingFactory;
-    private final Class<B> bindingClass;
-
     AdaptingTracker(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 void open(final boolean trackAllServices) {
-        LOG.debug("Starting tracker for {}", bindingClass.getName());
-        super.open(trackAllServices);
-        LOG.debug("Tracker for {} started", bindingClass.getName());
+            final Function<D, B> bindingFactory) {
+        super(ctx, domClass, bindingClass, bindingFactory);
     }
 
     @Override
-    public ServiceRegistration<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);
+    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);
@@ -71,20 +41,14 @@ final class AdaptingTracker<D extends DOMService, B extends BindingService>
     }
 
     @Override
-    public void modifiedService(final ServiceReference<D> reference, final ServiceRegistration<B> service) {
-        if (service != null && reference != null) {
-            final Dict newProps = Dict.fromReference(reference);
-            LOG.debug("Updating service {} with properties {}", service, newProps);
-            service.setProperties(newProps);
-        }
+    void removedService(final ServiceRegistration<B> service) {
+        service.unregister();
     }
 
     @Override
-    public void removedService(final ServiceReference<D> reference, final ServiceRegistration<B> service) {
-        if (service != null) {
-            context.ungetService(reference);
-            service.unregister();
-            LOG.debug("Unregistered service {}", service);
-        }
+    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);
     }
 }
index ab4fa7faef48d0ace3808dcf4da65e3cedc566d3..d30f5ffc24686fcf2b51eb23f4c9bbbc78919c47 100644 (file)
@@ -15,6 +15,7 @@ import java.util.Enumeration;
 import java.util.Map;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.binding.api.BindingService;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,7 +37,18 @@ final class Dict extends Dictionary<String, Object> {
             return EMPTY;
         }
 
-        final Map<String, Object> props = Maps.newHashMapWithExpectedSize(keys.length);
+        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);
         for (String key : keys) {
             // Ignore properties with our prefix: we are not exporting those
             if (!key.startsWith(ServiceProperties.PREFIX)) {
@@ -61,7 +73,7 @@ final class Dict extends Dictionary<String, Object> {
             }
         }
 
-        return new Dict(props);
+        return props;
     }
 
     @Override
index 3109e46759b3893ee1c95c808992dfcbd7d17ccb..82e631559a2ab6a1c4a82c58e47b6486a690a011 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.mdsal.dom.api.DOMService;
 import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentFactory;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -49,10 +50,14 @@ import org.slf4j.LoggerFactory;
 public final class DynamicBindingAdapter {
     private static final Logger LOG = LoggerFactory.getLogger(DynamicBindingAdapter.class);
 
-    private List<AdaptingTracker<?, ?>> trackers = ImmutableList.of();
+    private List<AbstractAdaptingTracker<?, ?, ?>> trackers = ImmutableList.of();
 
     @Reference
     AdapterFactory factory = null;
+    @Reference(target = "(component.factory=" + OSGiRpcConsumerRegistry.FACTORY_NAME + ")")
+    ComponentFactory rpcConsumerRegistryFactory = null;
+    @Reference(target = "(component.factory=" + OSGiRpcProviderService.FACTORY_NAME + ")")
+    ComponentFactory rpcProviderServiceFactory = null;
 
     @Activate
     void activate(final BundleContext ctx) {
@@ -65,10 +70,10 @@ public final class DynamicBindingAdapter {
                     factory::createNotificationService),
             new AdaptingTracker<>(ctx, DOMNotificationPublishService.class, NotificationPublishService.class,
                     factory::createNotificationPublishService),
-            new AdaptingTracker<>(ctx, DOMRpcService.class, RpcConsumerRegistry.class,
-                    factory::createRpcConsumerRegistry),
-            new AdaptingTracker<>(ctx, DOMRpcProviderService.class, RpcProviderService.class,
-                    factory::createRpcProviderService),
+            new AdaptingComponentTracker<>(ctx, DOMRpcService.class, RpcConsumerRegistry.class,
+                    factory::createRpcConsumerRegistry, rpcConsumerRegistryFactory),
+            new AdaptingComponentTracker<>(ctx, DOMRpcProviderService.class, RpcProviderService.class,
+                    factory::createRpcProviderService, rpcProviderServiceFactory),
             new AdaptingTracker<>(ctx, DOMActionService.class, ActionService.class, factory::createActionService),
             new AdaptingTracker<>(ctx, DOMActionProviderService.class, ActionProviderService.class,
                 factory::createActionProviderService));
@@ -82,7 +87,7 @@ public final class DynamicBindingAdapter {
     void deactivate() {
         LOG.debug("Stopping {} DOMService trackers", trackers.size());
         if (!trackers.isEmpty()) {
-            trackers.forEach(AdaptingTracker::close);
+            trackers.forEach(AbstractAdaptingTracker::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/OSGiRpcConsumerRegistry.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiRpcConsumerRegistry.java
new file mode 100644 (file)
index 0000000..fcf9dbc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+@Beta
+@Component(factory = OSGiRpcConsumerRegistry.FACTORY_NAME)
+public final class OSGiRpcConsumerRegistry extends AbstractAdaptedService<RpcConsumerRegistry>
+        implements RpcConsumerRegistry {
+    // OSGi DS Component Factory name
+    static final String FACTORY_NAME = "org.opendaylight.mdsal.binding.dom.adapter.osgi.OSGiRpcConsumerRegistry";
+
+    public OSGiRpcConsumerRegistry() {
+        super(RpcConsumerRegistry.class);
+    }
+
+    @Override
+    public <T extends RpcService> T getRpcService(final Class<T> serviceInterface) {
+        return delegate().getRpcService(serviceInterface);
+    }
+
+    @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/OSGiRpcProviderService.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/osgi/OSGiRpcProviderService.java
new file mode 100644 (file)
index 0000000..77ff3cd
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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 java.util.Set;
+import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+@Beta
+@Component(factory = OSGiRpcProviderService.FACTORY_NAME)
+public final class OSGiRpcProviderService extends AbstractAdaptedService<RpcProviderService>
+        implements RpcProviderService {
+    // OSGi DS Component Factory name
+    static final String FACTORY_NAME = "org.opendaylight.mdsal.binding.dom.adapter.osgi.OSGiRpcProviderService";
+
+    public OSGiRpcProviderService() {
+        super(RpcProviderService.class);
+    }
+
+    @Override
+    public <S extends RpcService, T extends S> ObjectRegistration<T> registerRpcImplementation(final Class<S> type,
+            final T implementation) {
+        return delegate().registerRpcImplementation(type, implementation);
+    }
+
+    @Override
+    public <S extends RpcService, T extends S> ObjectRegistration<T> registerRpcImplementation(final Class<S> type,
+            final T implementation, final Set<InstanceIdentifier<?>> paths) {
+        return delegate().registerRpcImplementation(type, implementation, paths);
+    }
+
+    @Activate
+    void activate(final Map<String, ?> properties) {
+        start(properties);
+    }
+
+    @Deactivate
+    void deactivate() {
+        stop();
+    }
+}