SEBA-1006-Minor version upgrade

Change-Id: I186b1c2d49daa81dea73188e60934755f771981e
diff --git a/api/pom.xml b/api/pom.xml
index 6e1ca1b..8d53f86 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -28,6 +28,7 @@
 
     <artifactId>mcast-api</artifactId>
     <packaging>bundle</packaging>
+    <version>${mcast.api.version}</version>
 
     <dependencies>
         <dependency>
diff --git a/app/app.xml b/app/app.xml
index ec9ce34..252c45e 100644
--- a/app/app.xml
+++ b/app/app.xml
@@ -17,8 +17,10 @@
 <app name="org.opencord.mcast" origin="ONF" version="${project.version}"
      category="Traffic Steering" url="http://opencord.org" title="CORD Mcast app"
      featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
-     features="${project.artifactId}" apps="org.onosproject.mcast,org.opencord.sadis">
+     features="${project.artifactId}">
     <description>${project.description}</description>
-    <artifact>mvn:${project.groupId}/mcast-api/${project.version}</artifact>
+    <artifact>mvn:${project.groupId}/mcast-api/${mcast.api.version}</artifact>
     <artifact>mvn:${project.groupId}/${project.artifactId}/${project.version}</artifact>
+    <artifact>mvn:${project.groupId}/sadis-api/${sadis.api.version}</artifact>
+    <artifact>mvn:org.onosproject/onos-apps-mcast-api/${onos.version}</artifact>
 </app>
diff --git a/app/features.xml b/app/features.xml
index 27289ef..42e699b 100644
--- a/app/features.xml
+++ b/app/features.xml
@@ -18,7 +18,9 @@
     <feature name="${project.artifactId}" version="${project.version}"
              description="${project.description}">
         <feature>onos-api</feature>
-        <bundle>mvn:${project.groupId}/mcast-api/${project.version}</bundle>
+        <bundle>mvn:${project.groupId}/mcast-api/${mcast.api.version}</bundle>
         <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+        <bundle>mvn:${project.groupId}/sadis-api/${sadis.api.version}</bundle>
+        <bundle>mvn:org.onosproject/onos-apps-mcast-api/${onos.version}</bundle>
     </feature>
 </features>
diff --git a/app/pom.xml b/app/pom.xml
index 5a922e9..74b4e3e 100644
--- a/app/pom.xml
+++ b/app/pom.xml
@@ -35,10 +35,6 @@
         <onos.app.category>Traffic Steering</onos.app.category>
         <onos.app.title>CORD Multicast App</onos.app.title>
         <onos.app.url>http://opencord.org</onos.app.url>
-        <onos.app.requires>
-            org.onosproject.mcast,
-            org.opencord.sadis
-        </onos.app.requires>
     </properties>
 
     <dependencies>
@@ -76,7 +72,7 @@
         <dependency>
             <groupId>org.opencord</groupId>
             <artifactId>mcast-api</artifactId>
-            <version>${project.version}</version>
+            <version>${mcast.api.version}</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
diff --git a/app/src/main/java/org/opencord/cordmcast/impl/CordMcast.java b/app/src/main/java/org/opencord/cordmcast/impl/CordMcast.java
index c8860d0..b51785d 100644
--- a/app/src/main/java/org/opencord/cordmcast/impl/CordMcast.java
+++ b/app/src/main/java/org/opencord/cordmcast/impl/CordMcast.java
@@ -76,6 +76,7 @@
 import org.osgi.service.component.annotations.Modified;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
 import org.slf4j.Logger;
 
 import java.util.Dictionary;
@@ -104,10 +105,12 @@
  */
 @Component(immediate = true,
         property = {
-        VLAN_ENABLED + ":Boolean=" + DEFAULT_VLAN_ENABLED,
-        PRIORITY + ":Integer=" + DEFAULT_PRIORITY,
-})
+                VLAN_ENABLED + ":Boolean=" + DEFAULT_VLAN_ENABLED,
+                PRIORITY + ":Integer=" + DEFAULT_PRIORITY,
+        })
 public class CordMcast implements CordMcastService {
+    private static final String MCAST_NOT_RUNNING = "Multicast is not running.";
+    private static final String SADIS_NOT_RUNNING = "Sadis is not running.";
     private static final String APP_NAME = "org.opencord.mcast";
 
     private final Logger log = getLogger(getClass());
@@ -115,8 +118,11 @@
     private static final int DEFAULT_PRIORITY = 500;
     private static final short DEFAULT_MCAST_VLAN = 4000;
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    protected MulticastRouteService mcastService;
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
+            bind = "bindMcastRouteService",
+            unbind = "unbindMcastRouteService",
+            policy = ReferencePolicy.DYNAMIC)
+    protected volatile MulticastRouteService mcastService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected FlowObjectiveService flowObjectiveService;
@@ -145,8 +151,11 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     private LeadershipService leadershipService;
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    protected SadisService sadisService;
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
+            bind = "bindSadisService",
+            unbind = "unbindSadisService",
+            policy = ReferencePolicy.DYNAMIC)
+    protected volatile SadisService sadisService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected CordMcastStatisticsService cordMcastStatisticsService;
@@ -190,12 +199,15 @@
 
     // lock to synchronize local operations
     private final Lock mcastLock = new ReentrantLock();
+
     private void mcastLock() {
         mcastLock.lock();
     }
+
     private void mcastUnlock() {
         mcastLock.unlock();
     }
+
     private ExecutorService eventExecutor;
 
     //Device listener to purge groups upon device disconnection.
@@ -224,14 +236,16 @@
 
         networkConfig.registerConfigFactory(cordMcastConfigFactory);
         networkConfig.addListener(configListener);
-        mcastService.addListener(listener);
-
-        mcastService.getRoutes().stream()
-                .map(r -> new ImmutablePair<>(r, mcastService.sinks(r)))
-                .filter(pair -> pair.getRight() != null && !pair.getRight().isEmpty())
-                .forEach(pair -> pair.getRight().forEach(sink -> addSink(pair.getLeft(),
-                                                                          sink)));
-
+        if (mcastService != null) {
+            mcastService.addListener(listener);
+            mcastService.getRoutes().stream()
+                    .map(r -> new ImmutablePair<>(r, mcastService.sinks(r)))
+                    .filter(pair -> pair.getRight() != null && !pair.getRight().isEmpty())
+                    .forEach(pair -> pair.getRight().forEach(sink -> addSink(pair.getLeft(),
+                            sink)));
+        } else {
+            log.warn(MCAST_NOT_RUNNING);
+        }
         McastConfig config = networkConfig.getConfig(coreAppId, CORD_MCAST_CONFIG_CLASS);
         updateConfig(config);
         deviceService.addListener(deviceListener);
@@ -259,16 +273,38 @@
     public void deactivate() {
         deviceService.removeListener(deviceListener);
         componentConfigService.unregisterProperties(getClass(), false);
-        mcastService.removeListener(listener);
+        if (mcastService != null) {
+            mcastService.removeListener(listener);
+        }
         networkConfig.removeListener(configListener);
         networkConfig.unregisterConfigFactory(cordMcastConfigFactory);
         eventExecutor.shutdown();
         eventExecutor = null;
-        groups.clear();
-        groups.destroy();
         log.info("Stopped");
     }
 
+    protected void bindSadisService(SadisService service) {
+        sadisService = service;
+        log.info("Sadis-service binds to onos.");
+    }
+
+    protected void unbindSadisService(SadisService service) {
+        sadisService = null;
+        log.info("Sadis-service unbinds from onos.");
+    }
+
+    protected void bindMcastRouteService(MulticastRouteService service) {
+        mcastService = service;
+        mcastService.addListener(listener);
+        log.info("Multicast route service binds to onos.");
+    }
+
+    protected void unbindMcastRouteService(MulticastRouteService service) {
+        service.removeListener(listener);
+        mcastService = null;
+        log.info("Multicast route service unbinds from onos.");
+    }
+
     /**
      * Updates the stats service with current VLAN config values.
      */
@@ -289,22 +325,22 @@
                     //On Success of removing the fwd objective we remove also the group.
                     Consumer<Objective> onSuccess = (objective) -> {
                         log.debug("Successfully removed fwd objective for {} on {}, " +
-                                          "removing next objective {}", groupInfo.group,
-                                  groupInfo.getDevice(), next.getNextId());
+                                        "removing next objective {}", groupInfo.group,
+                                groupInfo.getDevice(), next.getNextId());
                         eventExecutor.submit(() -> flowObjectiveService.next(groupInfo.getDevice(),
-                                                                             nextObject(next.getNextId(),
-                                                             null,
-                                                             NextType.Remove, groupInfo.group)));
+                                nextObject(next.getNextId(),
+                                        null,
+                                        NextType.Remove, groupInfo.group)));
                     };
 
                     ObjectiveContext context =
                             new DefaultObjectiveContext(onSuccess, (objective, error) ->
                                     log.warn("Failed to remove {} on {}: {}",
-                                             groupInfo.group, next.getNextId(), error));
+                                            groupInfo.group, next.getNextId(), error));
                     // remove the flow rule
                     flowObjectiveService.forward(groupInfo.getDevice(),
-                                                 fwdObject(next.getNextId(),
-                                                           groupInfo.group).remove(context));
+                            fwdObject(next.getNextId(),
+                                    groupInfo.group).remove(context));
 
                 }
             });
@@ -349,8 +385,9 @@
 
     /**
      * Processes previous, and new sinks then finds the sinks to be removed.
+     *
      * @param prevSinks the previous sinks to be evaluated
-     * @param newSinks the new sinks to be evaluated
+     * @param newSinks  the new sinks to be evaluated
      * @returnt the set of the sinks to be removed
      */
     private Set<ConnectPoint> getSinksToBeRemoved(Map<HostId, Set<ConnectPoint>> prevSinks,
@@ -361,7 +398,8 @@
 
     /**
      * Processes previous, and new sinks then finds the sinks to be added.
-     * @param newSinks the new sinks to be processed
+     *
+     * @param newSinks     the new sinks to be processed
      * @param allPrevSinks all previous sinks
      * @return the set of the sinks to be added
      */
@@ -372,6 +410,7 @@
 
     /**
      * Gets single-homed sinks that are in set1 but not in set2.
+     *
      * @param sinkSet1 the first sink map
      * @param sinkSet2 the second sink map
      * @return a set containing all the single-homed sinks found in set1 but not in set2
@@ -390,14 +429,14 @@
                 Sets.newHashSet() :
                 sinkSet2.get(HostId.NONE);
         return Sets.difference(sinksToBeProcessed, singleHomedSinksOfSet2);
-    };
+    }
 
 
     private void removeSinks(McastEvent event) {
         mcastLock();
         try {
             Set<ConnectPoint> sinksToBeRemoved = getSinksToBeRemoved(event.prevSubject().sinks(),
-                                                                     event.subject().sinks());
+                    event.subject().sinks());
             sinksToBeRemoved.forEach(sink -> removeSink(event.subject().route().group(), sink));
         } finally {
             mcastUnlock();
@@ -407,7 +446,7 @@
     private void removeSink(IpAddress group, ConnectPoint sink) {
         if (!isLocalLeader(sink.deviceId())) {
             log.debug("Not the leader of {}. Skip sink_removed event for the sink {} and group {}",
-                      sink.deviceId(), sink, group);
+                    sink.deviceId(), sink, group);
             return;
         }
 
@@ -542,6 +581,10 @@
     private Optional<SubscriberAndDeviceInformation> getSubscriberAndDeviceInformation(String serialNumber) {
         long start = System.currentTimeMillis();
         try {
+            if (sadisService == null) {
+                log.warn(SADIS_NOT_RUNNING);
+                return Optional.empty();
+            }
             return Optional.ofNullable(sadisService.getSubscriberInfoService().get(serialNumber));
         } finally {
             if (log.isDebugEnabled()) {
@@ -682,7 +725,7 @@
         }
     }
 
-    private enum NextType { AddNew, AddToExisting, Remove, RemoveFromExisting };
+    private enum NextType { AddNew, AddToExisting, Remove, RemoveFromExisting }
 
     private NextObjective nextObject(Integer nextId, PortNumber port,
                                      NextType nextType, IpAddress mcastIp) {
diff --git a/app/src/main/java/org/opencord/cordmcast/impl/CordMcastStatisticsManager.java b/app/src/main/java/org/opencord/cordmcast/impl/CordMcastStatisticsManager.java
index e2f4779..e56118b 100644
--- a/app/src/main/java/org/opencord/cordmcast/impl/CordMcastStatisticsManager.java
+++ b/app/src/main/java/org/opencord/cordmcast/impl/CordMcastStatisticsManager.java
@@ -16,6 +16,7 @@
 package org.opencord.cordmcast.impl;
 
 
+import com.google.common.collect.Lists;
 import org.onlab.packet.VlanId;
 import org.onlab.util.SafeRecurringTask;
 import org.onosproject.cfg.ComponentConfigService;
@@ -35,6 +36,7 @@
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
 import org.slf4j.Logger;
 
 import java.util.Dictionary;
@@ -63,11 +65,14 @@
 public class CordMcastStatisticsManager
         extends AbstractListenerManager<CordMcastStatisticsEvent, CordMcastStatisticsEventListener>
         implements CordMcastStatisticsService {
-
+    private static final String MCAST_NOT_RUNNING = "Multicast is not running.";
     private static final String CORD_MCAST_STATISTICS_LEADERSHIP = "cord-mcast-statistics-leadership";
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY)
-    protected MulticastRouteService mcastService;
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL,
+            bind = "bindMcastRouteService",
+            unbind = "unbindMcastRouteService",
+            policy = ReferencePolicy.DYNAMIC)
+    protected volatile MulticastRouteService mcastService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected ComponentConfigService componentConfigService;
@@ -127,7 +132,21 @@
         log.info("CordMcastStatisticsManager deactivated.");
     }
 
+    protected void bindMcastRouteService(MulticastRouteService service) {
+        mcastService = service;
+        log.info("Multicast route service binds to onos.");
+    }
+
+    protected void unbindMcastRouteService(MulticastRouteService service) {
+        mcastService = null;
+        log.info("Multicast route service unbinds from onos.");
+    }
+
     public List<CordMcastStatistics> getMcastDetails() {
+        if (mcastService == null) {
+            log.warn(MCAST_NOT_RUNNING);
+            return Lists.newArrayList();
+        }
         List<CordMcastStatistics> mcastData = new ArrayList<CordMcastStatistics>();
         Set<McastRoute> routes = mcastService.getRoutes();
         routes.forEach(route -> {
diff --git a/app/src/test/java/org/opencord/cordmcast/impl/McastTestBase.java b/app/src/test/java/org/opencord/cordmcast/impl/McastTestBase.java
index 758be58..1d6b815 100644
--- a/app/src/test/java/org/opencord/cordmcast/impl/McastTestBase.java
+++ b/app/src/test/java/org/opencord/cordmcast/impl/McastTestBase.java
@@ -262,6 +262,10 @@
         }
 
         @Override
+        public void clearLocalData() {
+        }
+
+        @Override
         public void invalidateAll() {
         }
 
diff --git a/pom.xml b/pom.xml
index 3e9750c..ed00947 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onosproject</groupId>
         <artifactId>onos-dependencies</artifactId>
-        <version>2.2.2</version>
+        <version>2.2.7</version>
     </parent>
 
     <groupId>org.opencord</groupId>
@@ -33,7 +33,8 @@
     <description>CORD Multicast application</description>
 
     <properties>
-        <sadis.api.version>5.1.0</sadis.api.version>
+        <sadis.api.version>5.3.0-SNAPSHOT</sadis.api.version>
+        <mcast.api.version>2.2.0-SNAPSHOT</mcast.api.version>
     </properties>
 
     <modules>