ONOS-2091 Installing app when already installed will now raise an error

Change-Id: I4dacd63bf4a99244b23b932d35dd9cbd088548c1
diff --git a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
index 78fd0b9..1b1c23b 100644
--- a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
+++ b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
@@ -50,6 +50,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
+import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.io.ByteStreams.toByteArray;
 import static com.google.common.io.Files.createParentDirs;
 import static com.google.common.io.Files.write;
@@ -108,7 +109,7 @@
      *
      * @return top-level directory path
      */
-    protected String getRootPath() {
+    public String getRootPath() {
         return root.getPath();
     }
 
@@ -179,6 +180,8 @@
             boolean plainXml = isPlainXml(cache);
             ApplicationDescription desc = plainXml ?
                     parsePlainAppDescription(bis) : parseZippedAppDescription(bis);
+            checkState(!appFile(desc.name(), APP_XML).exists(),
+                       "Application %s already installed", desc.name());
 
             if (plainXml) {
                 expandPlainApplication(cache, desc);
@@ -309,6 +312,7 @@
     private void expandPlainApplication(byte[] stream, ApplicationDescription desc)
             throws IOException {
         File file = appFile(desc.name(), APP_XML);
+        checkState(!file.getParentFile().exists(), "Application already installed");
         createParentDirs(file);
         write(stream, file);
     }
diff --git a/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java b/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java
index 9894174..153b024 100644
--- a/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java
+++ b/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java
@@ -93,7 +93,6 @@
     @Override
     public Set<Application> getApplications() {
         checkPermission(Permission.APP_READ);
-
         return store.getApplications();
     }
 
@@ -108,7 +107,6 @@
     @Override
     public Application getApplication(ApplicationId appId) {
         checkPermission(Permission.APP_READ);
-
         checkNotNull(appId, APP_ID_NULL);
         return store.getApplication(appId);
     }
@@ -116,7 +114,6 @@
     @Override
     public ApplicationState getState(ApplicationId appId) {
         checkPermission(Permission.APP_READ);
-
         checkNotNull(appId, APP_ID_NULL);
         return store.getState(appId);
     }
@@ -124,7 +121,6 @@
     @Override
     public Set<Permission> getPermissions(ApplicationId appId) {
         checkPermission(Permission.APP_READ);
-
         checkNotNull(appId, APP_ID_NULL);
         return store.getPermissions(appId);
     }
@@ -167,14 +163,12 @@
     @Override
     public void addListener(ApplicationListener listener) {
         checkPermission(Permission.APP_EVENT);
-
         listenerRegistry.addListener(listener);
     }
 
     @Override
     public void removeListener(ApplicationListener listener) {
         checkPermission(Permission.APP_EVENT);
-
         listenerRegistry.removeListener(listener);
     }
 
diff --git a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java
index a6fb24c..0e7a16e 100644
--- a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java
+++ b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java
@@ -19,6 +19,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.onlab.util.Tools;
 import org.onosproject.app.ApplicationEvent;
 import org.onosproject.app.ApplicationStoreDelegate;
 import org.onosproject.common.app.ApplicationArchive;
@@ -28,6 +29,10 @@
 import org.onosproject.core.ApplicationIdStoreAdapter;
 import org.onosproject.core.DefaultApplicationId;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.Random;
+
 import static org.junit.Assert.assertEquals;
 import static org.onosproject.app.ApplicationEvent.Type.APP_INSTALLED;
 import static org.onosproject.app.ApplicationEvent.Type.APP_DEACTIVATED;
@@ -42,23 +47,33 @@
  */
 public class SimpleApplicationStoreTest {
 
-    private SimpleApplicationStore store = new SimpleApplicationStore();
+    static final String ROOT = "/tmp/app-junit/";
+    static final String STORE = ROOT + new Random().nextInt(1000) + "/foo";
+
+    private TestApplicationStore store = new TestApplicationStore();
     private TestDelegate delegate = new TestDelegate();
+    private static final Object LOCK = new Object();
 
     @Before
     public void setUp() {
         store.idStore = new TestIdStore();
+        store.setRootPath(STORE);
         store.setDelegate(delegate);
         store.activate();
     }
 
     @After
-    public void tearDown() {
+    public void tearDown() throws IOException {
+        if (new File(ROOT).exists()) {
+            Tools.removeDirectory(ROOT);
+        }
         store.deactivate();
     }
 
     private Application createTestApp() {
-        return store.create(ApplicationArchive.class.getResourceAsStream("app.zip"));
+        synchronized (LOCK) {
+            return store.create(ApplicationArchive.class.getResourceAsStream("app.zip"));
+        }
     }
 
     @Test
@@ -132,4 +147,11 @@
             this.event = event;
         }
     }
+
+    private class TestApplicationStore extends SimpleApplicationStore {
+        @Override
+        public void setRootPath(String root) {
+            super.setRootPath(root);
+        }
+    }
 }
\ No newline at end of file