[ONOS-7083] Update application versions and activate active applications on upgrade

Change-Id: Id7f03a59835da2f15cf5e1e8efdeb9a82acf7ce1
diff --git a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
index c0b124c..7145a12 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
@@ -57,6 +57,7 @@
 import org.onosproject.store.service.Topic;
 import org.onosproject.store.service.Versioned;
 import org.onosproject.store.service.DistributedPrimitive.Status;
+import org.onosproject.upgrade.UpgradeService;
 import org.slf4j.Logger;
 
 import java.io.ByteArrayInputStream;
@@ -130,6 +131,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ApplicationIdStore idStore;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected UpgradeService upgradeService;
+
     private final InternalAppsListener appsListener = new InternalAppsListener();
     private final Consumer<Application> appActivator = new AppActivator();
 
@@ -184,16 +188,53 @@
         apps.addListener(appsListener, activationExecutor);
         apps.addStatusChangeListener(statusChangeListener);
         coreAppId = getId(CoreService.CORE_APP_NAME);
+
+        upgradeExistingApplications();
         log.info("Started");
     }
 
     /**
+     * Upgrades application versions for existing applications that are stored on disk after an upgrade.
+     */
+    private void upgradeExistingApplications() {
+        if (upgradeService.isUpgrading() && upgradeService.isLocalUpgraded()) {
+            getApplicationNames().forEach(appName -> {
+                // Only update the application version if the application has already been installed.
+                ApplicationId appId = getId(appName);
+                if (appId != null) {
+                    Application application = getApplication(appId);
+                    if (application != null) {
+                        InternalApplicationHolder appHolder = Versioned.valueOrNull(apps.get(application.id()));
+
+                        // Load the application description from disk. If the version doesn't match the persisted
+                        // version, update the stored application with the new version.
+                        ApplicationDescription appDesc = getApplicationDescription(appName);
+                        if (!appDesc.version().equals(application.version())) {
+                            Application newApplication = DefaultApplication.builder(application)
+                                    .withVersion(appDesc.version())
+                                    .build();
+                            InternalApplicationHolder newHolder = new InternalApplicationHolder(
+                                    newApplication, appHolder.state, appHolder.permissions);
+                            apps.put(newApplication.id(), newHolder);
+                        }
+
+                        // If the application was activated in the previous version, set the local state to active.
+                        if (appHolder.state == ACTIVATED) {
+                            setActive(appName);
+                            updateTime(appName);
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    /**
      * Processes existing applications from the distributed map. This is done to
      * account for events that this instance may be have missed due to a staggered start.
      */
     private void bootstrapExistingApplications() {
         apps.asJavaMap().forEach((appId, holder) -> setupApplicationAndNotify(appId, holder.app(), holder.state()));
-
     }
 
     /**
@@ -352,7 +393,6 @@
         activate(appId, true);
     }
 
-
     private void activate(ApplicationId appId, boolean updateTime) {
         Versioned<InternalApplicationHolder> vAppHolder = apps.get(appId);
         if (vAppHolder != null) {