You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by js...@apache.org on 2017/04/16 16:18:10 UTC

[2/8] geode git commit: GEODE-2686: Remove JarClassLoader

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDUnitTest.java
deleted file mode 100644
index a365899..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/JarDeployerDUnitTest.java
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import org.apache.geode.cache.execute.Execution;
-import org.apache.geode.cache.execute.FunctionService;
-import org.apache.geode.cache.execute.ResultCollector;
-import org.apache.geode.distributed.ConfigurationProperties;
-import org.apache.geode.distributed.DistributedSystem;
-import org.apache.geode.distributed.internal.InternalDistributedSystem;
-import org.apache.geode.test.dunit.Assert;
-import org.apache.geode.test.dunit.Host;
-import org.apache.geode.test.dunit.SerializableRunnable;
-import org.apache.geode.test.dunit.VM;
-import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
-import org.apache.geode.test.junit.categories.DistributedTest;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileLock;
-import java.nio.file.Files;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Pattern;
-
-/**
- * Unit tests for the JarDeployer class
- * 
- * @since GemFire 7.0
- */
-@Category(DistributedTest.class)
-@SuppressWarnings("serial")
-public class JarDeployerDUnitTest extends JUnit4CacheTestCase {
-
-  static FileLock savedFileLock = null;
-  private final ClassBuilder classBuilder = new ClassBuilder();
-
-  @Override
-  public final void preTearDownCacheTestCase() throws Exception {
-    JarDeployer jarDeployer = new JarDeployer();
-    for (JarClassLoader jarClassLoader : jarDeployer.findJarClassLoaders()) {
-      if (jarClassLoader.getJarName().startsWith("JarDeployerDUnit")) {
-        jarDeployer.undeploy(jarClassLoader.getJarName());
-      }
-    }
-    for (String functionName : FunctionService.getRegisteredFunctions().keySet()) {
-      if (functionName.startsWith("JarDeployerDUnit")) {
-        FunctionService.unregisterFunction(functionName);
-      }
-    }
-    disconnectAllFromDS();
-    deleteSavedJarFiles();
-  }
-
-
-
-  @Test
-  public void testDeployExclusiveLock() throws IOException, ClassNotFoundException {
-    final JarDeployer jarDeployer = new JarDeployer();
-    final File currentDir = new File(".").getAbsoluteFile();
-    final VM vm = Host.getHost(0).getVM(0);
-
-    // Deploy the Class JAR file
-    final File jarFile1 = jarDeployer.getNextVersionJarFile("JarDeployerDUnit.jar");
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDELA");
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDELA");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    assertNotNull(ClassPathLoader.getLatest().getResource("JarDeployerDUnitDELA.class"));
-
-    // Attempt to acquire an exclusive lock in the other VM
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        FileOutputStream outStream = null;
-        FileLock fileLock = null;
-
-        try {
-          outStream = new FileOutputStream(jarFile1, true);
-          fileLock = outStream.getChannel().tryLock(0, 1, false);
-          if (fileLock != null) {
-            fail("Should not have been able to obtain exclusive lock on file:"
-                + jarFile1.getAbsolutePath());
-          }
-        } catch (FileNotFoundException fnfex) {
-          Assert.fail("JAR file not found where expected", fnfex);
-        } catch (IOException ioex) {
-          Assert.fail("IOException when trying to obtain exclusive lock", ioex);
-        } finally {
-          if (outStream != null) {
-            try {
-              outStream.close();
-            } catch (IOException ioex) {
-              fail("Could not close lock file output stream");
-            }
-          }
-          if (fileLock != null) {
-            try {
-              fileLock.channel().close();
-            } catch (IOException ioex) {
-              fail("Could not close lock file channel");
-            }
-          }
-        }
-      }
-    });
-  }
-
-  @Test
-  public void testDeploySharedLock() throws IOException, ClassNotFoundException {
-    final JarDeployer jarDeployer = new JarDeployer();
-    final File currentDir = new File(".").getAbsoluteFile();
-    final VM vm = Host.getHost(0).getVM(0);
-
-    // Deploy the JAR file
-    final File jarFile1 = jarDeployer.getNextVersionJarFile("JarDeployerDUnit.jar");
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDSLA");
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDSLA");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    // Acquire a shared lock in the other VM
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        if (!jarFile1.exists()) {
-          fail("JAR file not found where expected: " + jarFile1.getName());
-        }
-        try {
-          JarDeployerDUnitTest.savedFileLock = acquireSharedLock(jarFile1);
-        } catch (IOException ioex) {
-          fail("Unable to acquire the shared file lock");
-        }
-      }
-    });
-
-    // Now update the JAR file and make sure the first one isn't deleted
-    jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDSLB");
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDSLB");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitC");
-      fail("Class should not be found on Classpath: JarDeployerDUniDSLA");
-    } catch (ClassNotFoundException expected) { // expected
-    }
-
-    if (!jarFile1.exists()) {
-      fail("JAR file should not have been deleted: " + jarFile1.getName());
-    }
-
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        try {
-          releaseLock(JarDeployerDUnitTest.savedFileLock, jarFile1);
-        } catch (IOException ioex) {
-          fail("Unable to release the shared file lock");
-        }
-      }
-    });
-  }
-
-  @Test
-  public void testUndeploySharedLock() throws IOException, ClassNotFoundException {
-    final JarDeployer jarDeployer = new JarDeployer();
-    final File currentDir = new File(".").getAbsoluteFile();
-    final VM vm = Host.getHost(0).getVM(0);
-
-    // Deploy the JAR file
-    final File jarFile1 = jarDeployer.getNextVersionJarFile("JarDeployerDUnit.jar");
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitUSL");
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitUSL");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    // Acquire a shared lock in the other VM
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        if (!jarFile1.exists()) {
-          fail("JAR file not found where expected: " + jarFile1.getName());
-        }
-        try {
-          JarDeployerDUnitTest.savedFileLock = acquireSharedLock(jarFile1);
-        } catch (IOException ioex) {
-          fail("Unable to acquire the shared file lock");
-        }
-      }
-    });
-
-    // Now undeploy the JAR file and make sure the first one isn't deleted
-    jarDeployer.undeploy("JarDeployerDUnit.jar");
-
-    if (!jarFile1.exists()) {
-      fail("JAR file should not have been deleted: " + jarFile1.getName());
-    }
-
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        try {
-          releaseLock(JarDeployerDUnitTest.savedFileLock, jarFile1);
-        } catch (IOException ioex) {
-          fail("Unable to release the shared file lock");
-        }
-      }
-    });
-  }
-
-  @Test
-  public void testDeployUpdateByAnotherVM() throws IOException, ClassNotFoundException {
-    final JarDeployer jarDeployer = new JarDeployer();
-    final File currentDir = new File(".").getAbsoluteFile();
-    final VM vm = Host.getHost(0).getVM(0);
-
-    final File jarFile1 = jarDeployer.getNextVersionJarFile("JarDeployerDUnit.jar");
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDUBAVMA");
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDUBAVMA");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    final File jarFile2 = jarDeployer.getNextVersionJarFile(jarFile1.getName());
-    final byte[] vmJarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDUBAVMB");
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        if (!jarFile1.exists()) {
-          fail("JAR file not found where expected: " + jarFile1.getName());
-        }
-
-        // The other VM writes out a newer version of the JAR file.
-        try {
-          writeJarBytesToFile(jarFile2, vmJarBytes);
-        } catch (IOException ioex) {
-          fail("Could not write JAR File");
-        }
-      }
-    });
-
-    // This VM is told to deploy the same JAR file.
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {vmJarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDUBAVMB");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDUBAVMA");
-      fail("Class should not be found on Classpath: JarDeployerDUnitDUBAVMA");
-    } catch (ClassNotFoundException expected) { // expected
-    }
-
-    if (!jarFile2.exists()) {
-      fail("JAR file should not have been deleted: " + jarFile2.getName());
-    }
-
-    // Make sure the second deploy didn't create a 3rd version of the JAR file.
-    final File jarFile3 = jarDeployer.getNextVersionJarFile(jarFile2.getName());
-    if (jarFile3.exists()) {
-      fail("JAR file should not have been created: " + jarFile3.getName());
-    }
-  }
-
-  @Test
-  public void testLoadPreviouslyDeployedJars() throws IOException {
-    final File parentJarFile = new File(JarDeployer.JAR_PREFIX + "JarDeployerDUnitAParent.jar#1");
-    final File usesJarFile = new File(JarDeployer.JAR_PREFIX + "JarDeployerDUnitUses.jar#1");
-    final File functionJarFile =
-        new File(JarDeployer.JAR_PREFIX + "JarDeployerDUnitFunction.jar#1");
-
-    // Write out a JAR files.
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("package jddunit.parent;");
-    stringBuffer.append("public class JarDeployerDUnitParent {");
-    stringBuffer.append("public String getValueParent() {");
-    stringBuffer.append("return \"PARENT\";}}");
-
-    byte[] jarBytes = this.classBuilder.createJarFromClassContent(
-        "jddunit/parent/JarDeployerDUnitParent", stringBuffer.toString());
-    FileOutputStream outStream = new FileOutputStream(parentJarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("package jddunit.uses;");
-    stringBuffer.append("public class JarDeployerDUnitUses {");
-    stringBuffer.append("public String getValueUses() {");
-    stringBuffer.append("return \"USES\";}}");
-
-    jarBytes = this.classBuilder.createJarFromClassContent("jddunit/uses/JarDeployerDUnitUses",
-        stringBuffer.toString());
-    outStream = new FileOutputStream(usesJarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("package jddunit.function;");
-    stringBuffer.append("import jddunit.parent.JarDeployerDUnitParent;");
-    stringBuffer.append("import jddunit.uses.JarDeployerDUnitUses;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer.append(
-        "public class JarDeployerDUnitFunction  extends JarDeployerDUnitParent implements Function {");
-    stringBuffer.append("private JarDeployerDUnitUses uses = new JarDeployerDUnitUses();");
-    stringBuffer.append("public boolean hasResult() {return true;}");
-    stringBuffer.append(
-        "public void execute(FunctionContext context) {context.getResultSender().lastResult(getValueParent() + \":\" + uses.getValueUses());}");
-    stringBuffer.append("public String getId() {return \"JarDeployerDUnitFunction\";}");
-    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
-    stringBuffer.append("public boolean isHA() {return false;}}");
-
-    ClassBuilder functionClassBuilder = new ClassBuilder();
-    functionClassBuilder.addToClassPath(parentJarFile.getAbsolutePath());
-    functionClassBuilder.addToClassPath(usesJarFile.getAbsolutePath());
-    jarBytes = functionClassBuilder.createJarFromClassContent(
-        "jddunit/function/JarDeployerDUnitFunction", stringBuffer.toString());
-    outStream = new FileOutputStream(functionJarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-
-    // Start the distributed system and check to see if the function executes correctly
-    DistributedSystem distributedSystem = getSystem();
-    getCache();
-
-    Execution execution =
-        FunctionService.onMember(distributedSystem, distributedSystem.getDistributedMember());
-    ResultCollector resultCollector = execution.execute("JarDeployerDUnitFunction");
-    @SuppressWarnings("unchecked")
-    List<String> result = (List<String>) resultCollector.getResult();
-    assertEquals("PARENT:USES", result.get(0));
-  }
-
-  @Test
-  public void testDeployToAlternateDirectory() throws IOException, ClassNotFoundException {
-    final File alternateDir = new File("JarDeployerDUnit");
-    alternateDir.mkdir();
-
-    // Add the alternate directory to the distributed system, get it back out, and then create
-    // a JarDeployer object with it.
-    Properties properties = new Properties();
-    properties.put(ConfigurationProperties.DEPLOY_WORKING_DIR, alternateDir.getAbsolutePath());
-    InternalDistributedSystem distributedSystem = getSystem(properties);
-    final JarDeployer jarDeployer =
-        new JarDeployer(distributedSystem.getConfig().getDeployWorkingDir());
-
-    File jarFile = jarDeployer.getNextVersionJarFile("JarDeployerDUnit.jar");
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDTAC");
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-
-    try {
-      ClassPathLoader.getLatest().forName("JarDeployerDUnitDTAC");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    if (!jarFile.exists()) {
-      fail("JAR file not found where expected: " + jarFile.getName());
-    }
-
-    if (!doesFileMatchBytes(jarFile, jarBytes)) {
-      fail("Contents of JAR file do not match those provided: " + jarFile.getName());
-    }
-  }
-
-
-
-  @Test
-  public void testSuspendAndResume() throws IOException, ClassNotFoundException {
-    AtomicReference<Boolean> okayToResume = new AtomicReference<>(false);
-
-    final JarDeployer jarDeployer = new JarDeployer();
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitSAR");
-    final JarDeployer suspendingJarDeployer = new JarDeployer();
-    final CountDownLatch latch = new CountDownLatch(1);
-
-    Thread thread = new Thread() {
-      @Override
-      public void run() {
-        try {
-          suspendingJarDeployer.suspendAll();
-          latch.countDown();
-          Thread.sleep(3000);
-        } catch (InterruptedException iex) {
-          // It doesn't matter, just fail the test
-        }
-        okayToResume.set(true);
-        suspendingJarDeployer.resumeAll();
-      }
-    };
-    thread.start();
-
-    try {
-      latch.await();
-    } catch (InterruptedException iex) {
-      // It doesn't matter, just fail the test
-    }
-    jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-    if (!okayToResume.get()) {
-      fail("JarDeployer did not suspend as expected");
-    }
-  }
-
-
-  @Test
-  public void testZeroLengthFile() throws IOException, ClassNotFoundException {
-    final JarDeployer jarDeployer = new JarDeployer();
-
-    try {
-      jarDeployer.deploy(new String[] {"JarDeployerDUnitZLF.jar"}, new byte[][] {new byte[0]});
-      fail("Zero length files are not deployable");
-    } catch (IllegalArgumentException expected) {
-      // Expected
-    }
-
-    try {
-      jarDeployer.deploy(new String[] {"JarDeployerDUnitZLF1.jar", "JarDeployerDUnitZLF2.jar"},
-          new byte[][] {this.classBuilder.createJarFromName("JarDeployerDUnitZLF1"), new byte[0]});
-      fail("Zero length files are not deployable");
-    } catch (IllegalArgumentException expected) {
-      // Expected
-    }
-  }
-
-  @Test
-  public void testInvalidJarFile() throws IOException, ClassNotFoundException {
-    final JarDeployer jarDeployer = new JarDeployer();
-
-    try {
-      jarDeployer.deploy(new String[] {"JarDeployerDUnitIJF.jar"},
-          new byte[][] {"INVALID JAR CONTENT".getBytes()});
-      fail("Non-JAR files are not deployable");
-    } catch (IllegalArgumentException expected) {
-      // Expected
-    }
-
-    try {
-      jarDeployer.deploy(new String[] {"JarDeployerDUnitIJF1.jar", "JarDeployerDUnitIJF2.jar"},
-          new byte[][] {this.classBuilder.createJarFromName("JarDeployerDUnitIJF1"),
-              "INVALID JAR CONTENT".getBytes()});
-      fail("Non-JAR files are not deployable");
-    } catch (IllegalArgumentException expected) {
-      // Expected
-    }
-
-    final VM vm = Host.getHost(0).getVM(1);
-    vm.invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        File invalidFile = new File(JarDeployer.JAR_PREFIX + "JarDeployerDUnitIJF.jar#3");
-        try {
-          RandomAccessFile randomAccessFile = new RandomAccessFile(invalidFile, "rw");
-          randomAccessFile.write("GARBAGE".getBytes(), 0, 7);
-          randomAccessFile.close();
-        } catch (IOException ioex) {
-          Assert.fail("Error trying to create garbage file for test", ioex);
-        }
-
-        getSystem();
-        getCache();
-
-        if (invalidFile.exists()) {
-          fail("Invalid JAR file should have been deleted at startup");
-        }
-      }
-    });
-  }
-
-  FileLock acquireSharedLock(final File file) throws IOException {
-    return new FileInputStream(file).getChannel().lock(0, 1, true);
-  }
-
-  void releaseLock(final FileLock fileLock, final File lockFile) throws IOException {
-    if (lockFile == null) {
-      return;
-    }
-
-    try {
-      if (fileLock != null) {
-        fileLock.release();
-        fileLock.channel().close();
-      }
-    } finally {
-      if (!lockFile.delete()) {
-        lockFile.deleteOnExit();
-      }
-    }
-  }
-
-  protected boolean doesFileMatchBytes(final File file, final byte[] bytes) throws IOException {
-    // If the don't have the same number of bytes then nothing to do
-    if (file.length() != bytes.length) {
-      return false;
-    }
-
-    // Open the file then loop comparing each byte
-    int index = 0;
-    try (InputStream inStream = new FileInputStream(file)) {
-      for (; index < bytes.length; index++) {
-        if (((byte) inStream.read()) != bytes[index])
-          break;
-      }
-    }
-
-    // If we didn't get to the end then something was different
-    return index >= bytes.length;
-  }
-
-  private void deleteSavedJarFiles() throws IOException {
-    Pattern pattern = Pattern.compile("^" + JarDeployer.JAR_PREFIX + "JarDeployerDUnit.*#\\d++$");
-    File[] files = new File(".").listFiles((dir1, name) -> pattern.matcher(name).matches());
-    if (files != null) {
-      for (File file : files) {
-        Files.delete(file.toPath());
-      }
-    }
-  }
-
-  void writeJarBytesToFile(File jarFile, byte[] jarBytes) throws IOException {
-    final OutputStream outStream = new FileOutputStream(jarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-  }
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/internal/JarDeployerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/JarDeployerIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/JarDeployerIntegrationTest.java
index 71daecc..9e42c20 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/JarDeployerIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/JarDeployerIntegrationTest.java
@@ -11,9 +11,12 @@
  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
+ *
  */
+
 package org.apache.geode.internal;
 
+
 import static org.apache.geode.internal.Assert.fail;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -22,162 +25,187 @@ import org.apache.geode.test.junit.categories.IntegrationTest;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 import org.junit.experimental.categories.Category;
 import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
 import java.io.IOException;
-import java.nio.file.Files;
+import java.util.Set;
+import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @Category(IntegrationTest.class)
 public class JarDeployerIntegrationTest {
-
   private ClassBuilder classBuilder;
 
   @Rule
   public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
-  @Rule
-  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+  JarDeployer jarDeployer;
 
   @Before
   public void setup() {
-    System.setProperty("user.dir", temporaryFolder.getRoot().getAbsolutePath());
     classBuilder = new ClassBuilder();
-    ClassPathLoader.setLatestToDefault();
+    jarDeployer = new JarDeployer(temporaryFolder.getRoot());
   }
 
-  @Test
-  public void testDeployFileAndChange() throws Exception {
-    final JarDeployer jarDeployer = new JarDeployer();
+  private byte[] createJarWithClass(String className) throws IOException {
+    String stringBuilder = "package integration.parent;" + "public class " + className + " {}";
 
-    // First deploy of the JAR file
-    byte[] jarBytes = this.classBuilder.createJarFromName("ClassA");
-    JarClassLoader jarClassLoader =
-        jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes})[0];
-    File deployedJar = new File(jarClassLoader.getFileCanonicalPath());
+    return this.classBuilder.createJarFromClassContent("integration/parent/" + className,
+        stringBuilder);
+  }
+
+  @Test
+  public void testFileVersioning() throws Exception {
+    String jarName = "JarDeployerIntegrationTest.jar";
 
-    assertThat(deployedJar).exists();
-    assertThat(deployedJar.getName()).contains("#1");
-    assertThat(deployedJar.getName()).doesNotContain("#2");
+    byte[] firstJarBytes = createJarWithClass("ClassA");
 
-    assertThat(ClassPathLoader.getLatest().forName("ClassA")).isNotNull();
+    // First deploy of the JAR file
+    DeployedJar firstDeployedJar = jarDeployer.deployWithoutRegistering(jarName, firstJarBytes);
 
-    assertThat(doesFileMatchBytes(deployedJar, jarBytes));
+    assertThat(firstDeployedJar.getFile()).exists().hasBinaryContent(firstJarBytes);
+    assertThat(firstDeployedJar.getFile().getName()).contains(".v1.").doesNotContain(".v2.");
 
     // Now deploy an updated JAR file and make sure that the next version of the JAR file
-    // was created and the first one was deleted.
-    jarBytes = this.classBuilder.createJarFromName("ClassB");
-    JarClassLoader newJarClassLoader =
-        jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes})[0];
-    File nextDeployedJar = new File(newJarClassLoader.getFileCanonicalPath());
-
-    assertThat(nextDeployedJar.exists());
-    assertThat(nextDeployedJar.getName()).contains("#2");
-    assertThat(doesFileMatchBytes(nextDeployedJar, jarBytes));
+    // was created
+    byte[] secondJarBytes = createJarWithClass("ClassB");
 
-    assertThat(ClassPathLoader.getLatest().forName("ClassB")).isNotNull();
+    DeployedJar secondDeployedJar = jarDeployer.deployWithoutRegistering(jarName, secondJarBytes);
+    File secondDeployedJarFile = new File(secondDeployedJar.getFileCanonicalPath());
 
-    assertThatThrownBy(() -> ClassPathLoader.getLatest().forName("ClassA"))
-        .isExactlyInstanceOf(ClassNotFoundException.class);
+    assertThat(secondDeployedJarFile).exists().hasBinaryContent(secondJarBytes);
+    assertThat(secondDeployedJarFile.getName()).contains(".v2.").doesNotContain(".v1.");
 
-    assertThat(jarDeployer.findSortedOldVersionsOfJar("JarDeployerDUnit.jar")).hasSize(1);
+    File[] sortedOldJars = jarDeployer.findSortedOldVersionsOfJar(jarName);
+    assertThat(sortedOldJars).hasSize(2);
+    assertThat(sortedOldJars[0].getName()).contains(".v2.");
+    assertThat(sortedOldJars[1].getName()).contains(".v1.");
     assertThat(jarDeployer.findDistinctDeployedJars()).hasSize(1);
   }
 
   @Test
-  public void testDeployNoUpdateWhenNoChange() throws Exception {
-    final JarDeployer jarDeployer = new JarDeployer();
-
-    // First deploy of the JAR file
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDNUWNC");
-    JarClassLoader jarClassLoader =
-        jarDeployer.deploy(new String[] {"JarDeployerDUnit2.jar"}, new byte[][] {jarBytes})[0];
-    File deployedJar = new File(jarClassLoader.getFileCanonicalPath());
-
-    assertThat(deployedJar).exists();
-    assertThat(deployedJar.getName()).contains("#1");
-    JarClassLoader newJarClassLoader =
-        jarDeployer.deploy(new String[] {"JarDeployerDUnit2.jar"}, new byte[][] {jarBytes})[0];
-    assertThat(newJarClassLoader).isNull();
-  }
-
-  @Test
-  public void testDeployToInvalidDirectory() throws IOException, ClassNotFoundException {
+  public void testDeployToInvalidDirectory() throws Exception {
     final File alternateDir = new File(temporaryFolder.getRoot(), "JarDeployerDUnit");
     alternateDir.delete();
 
     final JarDeployer jarDeployer = new JarDeployer(alternateDir);
+
     final CyclicBarrier barrier = new CyclicBarrier(2);
     final byte[] jarBytes = this.classBuilder.createJarFromName("JarDeployerDUnitDTID");
 
     // Test to verify that deployment fails if the directory doesn't exist.
     assertThatThrownBy(() -> {
-      jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
+      jarDeployer.deployWithoutRegistering("JarDeployerIntegrationTest.jar", jarBytes);
     }).isInstanceOf(IOException.class);
 
     // Test to verify that deployment succeeds if the directory doesn't
     // initially exist, but is then created while the JarDeployer is looping
     // looking for a valid directory.
-    Thread thread = new Thread() {
-      @Override
-      public void run() {
-        try {
-          barrier.await();
-        } catch (Exception e) {
-          fail(e);
-        }
-
-        try {
-          jarDeployer.deploy(new String[] {"JarDeployerDUnit.jar"}, new byte[][] {jarBytes});
-        } catch (Exception e) {
-          fail(e);
-        }
-      }
-    };
-    thread.start();
-
-    try {
+    Future<Boolean> done = Executors.newSingleThreadExecutor().submit(() -> {
       barrier.await();
-      Thread.sleep(500);
-      alternateDir.mkdir();
-      thread.join();
-    } catch (Exception e) {
-      fail(e);
-    }
+      jarDeployer.deployWithoutRegistering("JarDeployerIntegrationTest.jar", jarBytes);
+      return true;
+    });
+
+    barrier.await();
+    Thread.sleep(500);
+    alternateDir.mkdir();
+    assertThat(done.get(2, TimeUnit.MINUTES)).isTrue();
   }
 
   @Test
   public void testVersionNumberCreation() throws Exception {
-    JarDeployer jarDeployer = new JarDeployer();
-
-    File versionedName = jarDeployer.getNextVersionJarFile("myJar.jar");
-    assertThat(versionedName.getName()).isEqualTo(JarDeployer.JAR_PREFIX + "myJar.jar" + "#1");
+    File versionedName = jarDeployer.getNextVersionedJarFile("myJar.jar");
+    assertThat(versionedName.getName()).isEqualTo("myJar.v1.jar");
 
     byte[] jarBytes = this.classBuilder.createJarFromName("ClassA");
-    JarClassLoader jarClassLoader =
-        jarDeployer.deploy(new String[] {"myJar.jar"}, new byte[][] {jarBytes})[0];
-    File deployedJar = new File(jarClassLoader.getFileCanonicalPath());
+    File deployedJarFile = jarDeployer.deployWithoutRegistering("myJar.jar", jarBytes).getFile();
 
-    assertThat(deployedJar.getName()).isEqualTo(JarDeployer.JAR_PREFIX + "myJar.jar" + "#1");
-    assertThat(jarDeployer.getNextVersionJarFile(deployedJar.getName()).getName())
-        .isEqualTo(JarDeployer.JAR_PREFIX + "myJar.jar" + "#2");
+    assertThat(deployedJarFile.getName()).isEqualTo("myJar.v1.jar");
 
+    File secondDeployedJarFile =
+        jarDeployer.deployWithoutRegistering("myJar.jar", jarBytes).getFile();
+
+    assertThat(secondDeployedJarFile.getName()).isEqualTo("myJar.v2.jar");
   }
 
   @Test
-  public void testVersionNumberMatcher() throws Exception {
-    JarDeployer jarDeployer = new JarDeployer();
-    int version = jarDeployer.extractVersionFromFilename(
-        temporaryFolder.newFile(JarDeployer.JAR_PREFIX + "MyJar.jar" + "#1"));
+  public void testVersionNumberMatcher() throws IOException {
+    int version =
+        jarDeployer.extractVersionFromFilename(temporaryFolder.newFile("MyJar.v1.jar").getName());
 
     assertThat(version).isEqualTo(1);
   }
 
-  private boolean doesFileMatchBytes(final File file, final byte[] bytes) throws IOException {
-    return bytes == Files.readAllBytes(file.toPath());
+  @Test
+  public void testRenamingOfOldJarFiles() throws Exception {
+    File deployDir = jarDeployer.getDeployDirectory();
+
+    File jarAVersion1 = new File(deployDir, "vf.gf#myJarA.jar#1");
+    this.classBuilder.writeJarFromName("ClassA", jarAVersion1);
+
+    File jarAVersion2 = new File(deployDir, "vf.gf#myJarA.jar#2");
+    this.classBuilder.writeJarFromName("ClassA", jarAVersion2);
+
+    File jarBVersion2 = new File(deployDir, "vf.gf#myJarB.jar#2");
+    this.classBuilder.writeJarFromName("ClassB", jarBVersion2);
+
+    File jarBVersion3 = new File(deployDir, "vf.gf#myJarB.jar#3");
+    this.classBuilder.writeJarFromName("ClassB", jarBVersion3);
+
+    Set<File> deployedJarsBeforeRename = Stream
+        .of(jarAVersion1, jarAVersion2, jarBVersion2, jarBVersion3).collect(Collectors.toSet());
+
+    jarDeployer.renameJarsWithOldNamingConvention();
+
+    deployedJarsBeforeRename.forEach(oldJar -> assertThat(oldJar).doesNotExist());
+
+    File renamedJarAVersion1 = new File(deployDir, "myJarA.v1.jar");
+    File renamedJarAVersion2 = new File(deployDir, "myJarA.v2.jar");
+    File renamedJarBVersion2 = new File(deployDir, "myJarB.v2.jar");
+    File renamedJarBVersion3 = new File(deployDir, "myJarB.v3.jar");
+    Set<File> expectedJarsAfterRename = Stream
+        .of(renamedJarAVersion1, renamedJarAVersion2, renamedJarBVersion2, renamedJarBVersion3)
+        .collect(Collectors.toSet());
+
+    Set<File> actualJarsInDeployDir =
+        Stream.of(jarDeployer.getDeployDirectory().listFiles()).collect(Collectors.toSet());
+
+    assertThat(actualJarsInDeployDir).isEqualTo(expectedJarsAfterRename);
   }
 
+  @Test
+  public void testOldJarNameMatcher() throws Exception {
+    File deployDir = jarDeployer.getDeployDirectory();
+
+    File jarAVersion1 = new File(deployDir, "vf.gf#myJarA.jar#1");
+    this.classBuilder.writeJarFromName("ClassA", jarAVersion1);
+
+    File jarAVersion2 = new File(deployDir, "vf.gf#myJarA.jar#2");
+    this.classBuilder.writeJarFromName("ClassA", jarAVersion2);
+
+    File jarBVersion2 = new File(deployDir, "vf.gf#myJarB.jar#2");
+    this.classBuilder.writeJarFromName("ClassB", jarBVersion2);
+
+    File jarBVersion3 = new File(deployDir, "vf.gf#myJarB.jar#3");
+    this.classBuilder.writeJarFromName("ClassB", jarBVersion3);
+
+    Set<File> jarsWithOldNamingConvention = Stream
+        .of(jarAVersion1, jarAVersion2, jarBVersion2, jarBVersion3).collect(Collectors.toSet());
+
+    jarsWithOldNamingConvention.forEach(
+        jarFile -> assertThat(jarDeployer.isOldNamingConvention(jarFile.getName())).isTrue());
+
+    Set<File> foundJarsWithOldNamingConvention = jarDeployer.findJarsWithOldNamingConvention();
+    assertThat(foundJarsWithOldNamingConvention).isEqualTo(jarsWithOldNamingConvention);
+  }
+
+
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/internal/cache/IncrementalBackupDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/IncrementalBackupDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/IncrementalBackupDUnitTest.java
index 0cc003e..dcbbeb0 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/IncrementalBackupDUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/IncrementalBackupDUnitTest.java
@@ -20,6 +20,22 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.geode.internal.ClassPathLoader;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.filefilter.DirectoryFileFilter;
 import org.apache.commons.io.filefilter.RegexFileFilter;
@@ -38,7 +54,7 @@ import org.apache.geode.cache.persistence.PersistentID;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.DistributedSystem;
 import org.apache.geode.internal.ClassBuilder;
-import org.apache.geode.internal.JarClassLoader;
+import org.apache.geode.internal.DeployedJar;
 import org.apache.geode.internal.JarDeployer;
 import org.apache.geode.internal.cache.persistence.BackupManager;
 import org.apache.geode.internal.util.IOUtils;
@@ -1078,15 +1094,16 @@ public class IncrementalBackupDUnitTest extends JUnit4CacheTestCase {
     /*
      * Deploy a "dummy"�jar to the VM.
      */
-    vm0.invoke(new SerializableCallable() {
+    File deployedJarFile = (File) vm0.invoke(new SerializableCallable() {
       @Override
       public Object call() throws Exception {
-        JarDeployer deployer = new JarDeployer();
-        deployer.deploy(new String[] {jarName}, new byte[][] {classBytes});
-        return null;
+        DeployedJar deployedJar =
+            ClassPathLoader.getLatest().getJarDeployer().deploy(jarName, classBytes);
+        return deployedJar.getFile();
       }
     });
 
+    assert (deployedJarFile.exists());
     /*
      * Perform backup. Make sure it is successful.
      */
@@ -1149,10 +1166,10 @@ public class IncrementalBackupDUnitTest extends JUnit4CacheTestCase {
     vm0.invoke(new SerializableCallable() {
       @Override
       public Object call() throws Exception {
-        JarDeployer deployer = new JarDeployer();
-        for (JarClassLoader jarClassLoader : deployer.findJarClassLoaders()) {
+        for (DeployedJar jarClassLoader : ClassPathLoader.getLatest().getJarDeployer()
+            .findDeployedJars()) {
           if (jarClassLoader.getJarName().startsWith(jarName)) {
-            deployer.undeploy(jarClassLoader.getJarName());
+            ClassPathLoader.getLatest().getJarDeployer().undeploy(jarClassLoader.getJarName());
           }
         }
         return null;

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java b/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
new file mode 100644
index 0000000..3149432
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/DeployJarTestSuite.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.management;
+
+import org.apache.geode.internal.ClassPathLoaderIntegrationTest;
+import org.apache.geode.internal.ClassPathLoaderTest;
+import org.apache.geode.internal.DeployedJarJUnitTest;
+import org.apache.geode.internal.JarDeployerIntegrationTest;
+import org.apache.geode.management.internal.cli.commands.DeployCommandRedeployDUnitTest;
+import org.apache.geode.management.internal.cli.commands.DeployCommandsDUnitTest;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({DeployedJarJUnitTest.class, DeployCommandsDUnitTest.class,
+    JarDeployerIntegrationTest.class, ClassPathLoaderIntegrationTest.class,
+    ClassPathLoaderTest.class, DeployCommandRedeployDUnitTest.class})
+public class DeployJarTestSuite {
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandRedeployDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandRedeployDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandRedeployDUnitTest.java
new file mode 100644
index 0000000..8280f5d
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandRedeployDUnitTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.management.internal.cli.commands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.geode.cache.execute.Execution;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.ClassBuilder;
+import org.apache.geode.internal.ClassPathLoader;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.test.dunit.rules.GfshShellConnectionRule;
+import org.apache.geode.test.dunit.rules.Locator;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.Server;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.List;
+
+@Category(DistributedTest.class)
+public class DeployCommandRedeployDUnitTest implements Serializable {
+  private static final String VERSION1 = "Version1";
+  private static final String VERSION2 = "Version2";
+
+  private static final String jarNameA = "DeployCommandRedeployDUnitTestA.jar";
+  private static final String functionA = "DeployCommandRedeployDUnitFunctionA";
+  private File jarAVersion1;
+  private File jarAVersion2;
+
+  private static final String jarNameB = "DeployCommandRedeployDUnitTestB.jar";
+  private static final String functionB = "DeployCommandRedeployDUnitFunctionB";
+  private static final String packageB = "jddunit.function";
+  private static final String fullyQualifiedFunctionB = packageB + "." + functionB;
+  private File jarBVersion1;
+  private File jarBVersion2;
+
+  private MemberVM locator;
+  private MemberVM server;
+
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Rule
+  public transient GfshShellConnectionRule gfshConnector = new GfshShellConnectionRule();
+
+  @Before
+  public void setup() throws Exception {
+    jarAVersion1 = createJarWithFunctionA(VERSION1);
+    jarAVersion2 = createJarWithFunctionA(VERSION2);
+
+    jarBVersion1 = createJarWithFunctionB(VERSION1);
+    jarBVersion2 = createJarWithFunctionB(VERSION2);
+
+    locator = lsRule.startLocatorVM(0);
+    server = lsRule.startServerVM(1, locator.getPort());
+
+    gfshConnector.connectAndVerify(locator);
+  }
+
+  @Test
+  public void redeployJarsWithNewVersionsOfFunctions() throws Exception {
+    gfshConnector.executeAndVerifyCommand("deploy --jar=" + jarAVersion1.getCanonicalPath());
+    server.invoke(() -> assertThatCanLoad(jarNameA, functionA));
+    server.invoke(() -> assertThatFunctionHasVersion(functionA, VERSION1));
+
+
+    gfshConnector.executeAndVerifyCommand("deploy --jar=" + jarBVersion1.getCanonicalPath());
+    server.invoke(() -> assertThatCanLoad(jarNameA, functionA));
+    server.invoke(() -> assertThatCanLoad(jarNameB, fullyQualifiedFunctionB));
+    server.invoke(() -> assertThatFunctionHasVersion(functionA, VERSION1));
+    server.invoke(() -> assertThatFunctionHasVersion(functionB, VERSION1));
+
+    gfshConnector.executeAndVerifyCommand("deploy --jar=" + jarBVersion2.getCanonicalPath());
+    server.invoke(() -> assertThatCanLoad(jarNameA, functionA));
+    server.invoke(() -> assertThatCanLoad(jarNameB, fullyQualifiedFunctionB));
+    server.invoke(() -> assertThatFunctionHasVersion(functionA, VERSION1));
+    server.invoke(() -> assertThatFunctionHasVersion(functionB, VERSION2));
+
+    gfshConnector.executeAndVerifyCommand("deploy --jar=" + jarAVersion2.getCanonicalPath());
+    server.invoke(() -> assertThatCanLoad(jarNameA, functionA));
+    server.invoke(() -> assertThatCanLoad(jarNameB, fullyQualifiedFunctionB));
+    server.invoke(() -> assertThatFunctionHasVersion(functionA, VERSION2));
+    server.invoke(() -> assertThatFunctionHasVersion(functionB, VERSION2));
+  }
+
+  // Note that jar A is a Declarable Function, while jar B is only a Function.
+  // Also, the function for jar A resides in the default package, whereas jar B specifies a package.
+  // This ensures that this test has identical coverage to some tests that it replaced.
+  private File createJarWithFunctionA(String version) throws Exception {
+    String classContents =
+        "import java.util.Properties;" + "import org.apache.geode.cache.Declarable;"
+            + "import org.apache.geode.cache.execute.Function;"
+            + "import org.apache.geode.cache.execute.FunctionContext;" + "public class " + functionA
+            + " implements Function, Declarable {" + "public String getId() {return \"" + functionA
+            + "\";}" + "public void init(Properties props) {}"
+            + "public void execute(FunctionContext context) {context.getResultSender().lastResult(\""
+            + version + "\");}" + "public boolean hasResult() {return true;}"
+            + "public boolean optimizeForWrite() {return false;}"
+            + "public boolean isHA() {return false;}}";
+
+    File jar = new File(lsRule.getTempFolder().newFolder(jarNameA + version), this.jarNameA);
+    ClassBuilder functionClassBuilder = new ClassBuilder();
+    functionClassBuilder.writeJarFromContent(functionA, classContents, jar);
+
+    return jar;
+  }
+
+  private File createJarWithFunctionB(String version) throws IOException {
+    String classContents =
+        "package " + packageB + ";" + "import org.apache.geode.cache.execute.Function;"
+            + "import org.apache.geode.cache.execute.FunctionContext;" + "public class " + functionB
+            + " implements Function {" + "public boolean hasResult() {return true;}"
+            + "public void execute(FunctionContext context) {context.getResultSender().lastResult(\""
+            + version + "\");}" + "public String getId() {return \"" + functionB + "\";}"
+            + "public boolean optimizeForWrite() {return false;}"
+            + "public boolean isHA() {return false;}}";
+
+    File jar = new File(lsRule.getTempFolder().newFolder(jarNameB + version), this.jarNameB);
+    ClassBuilder functionClassBuilder = new ClassBuilder();
+    functionClassBuilder.writeJarFromContent("jddunit/function/" + functionB, classContents, jar);
+
+    return jar;
+  }
+
+  private void assertThatFunctionHasVersion(String functionId, String version) {
+    GemFireCacheImpl gemFireCache = GemFireCacheImpl.getInstance();
+    DistributedSystem distributedSystem = gemFireCache.getDistributedSystem();
+    Execution execution =
+        FunctionService.onMember(distributedSystem, distributedSystem.getDistributedMember());
+    List<String> result = (List<String>) execution.execute(functionId).getResult();
+    assertThat(result.get(0)).isEqualTo(version);
+  }
+
+  private void assertThatCanLoad(String jarName, String className) throws ClassNotFoundException {
+    assertThat(ClassPathLoader.getLatest().getJarDeployer().findDeployedJar(jarName)).isNotNull();
+    assertThat(ClassPathLoader.getLatest().forName(className)).isNotNull();
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
index 7b0823b..6df2572 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DeployCommandsDUnitTest.java
@@ -14,53 +14,28 @@
  */
 package org.apache.geode.management.internal.cli.commands;
 
-import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
 import static org.apache.geode.distributed.ConfigurationProperties.GROUPS;
-import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT;
-import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER;
-import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_BIND_ADDRESS;
-import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_PORT;
-import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_START;
-import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
-import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
-import static org.apache.geode.distributed.ConfigurationProperties.NAME;
-import static org.apache.geode.test.dunit.Assert.assertEquals;
-import static org.apache.geode.test.dunit.Assert.assertFalse;
-import static org.apache.geode.test.dunit.Assert.assertTrue;
-import static org.apache.geode.test.dunit.Assert.fail;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertNotNull;
 
-import org.apache.geode.distributed.Locator;
-import org.apache.geode.distributed.internal.DistributionManager;
-import org.apache.geode.distributed.internal.InternalLocator;
-import org.apache.geode.distributed.internal.ClusterConfigurationService;
-import org.apache.geode.internal.AvailablePort;
-import org.apache.geode.internal.AvailablePortHelper;
 import org.apache.geode.internal.ClassBuilder;
-import org.apache.geode.internal.JarDeployer;
-import org.apache.geode.management.cli.Result;
-import org.apache.geode.management.internal.cli.i18n.CliStrings;
-import org.apache.geode.management.internal.cli.remote.CommandExecutionContext;
-import org.apache.geode.management.internal.cli.remote.CommandProcessor;
+import org.apache.geode.internal.ClassPathLoader;
 import org.apache.geode.management.internal.cli.result.CommandResult;
-import org.apache.geode.test.dunit.Assert;
-import org.apache.geode.test.dunit.Host;
-import org.apache.geode.test.dunit.SerializableRunnable;
-import org.apache.geode.test.dunit.VM;
-import org.apache.geode.test.dunit.Wait;
-import org.apache.geode.test.dunit.WaitCriterion;
-import org.apache.geode.test.dunit.rules.ServerStarterRule;
+import org.apache.geode.test.dunit.rules.GfshShellConnectionRule;
+import org.apache.geode.test.dunit.rules.Locator;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.Server;
 import org.apache.geode.test.junit.categories.DistributedTest;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.io.Serializable;
 import java.util.Properties;
-import java.util.regex.Pattern;
 
 /**
  * Unit tests for the DeployCommands class
@@ -69,453 +44,238 @@ import java.util.regex.Pattern;
  */
 @SuppressWarnings("serial")
 @Category(DistributedTest.class)
-public class DeployCommandsDUnitTest extends CliCommandTestBase {
-
-  private final Pattern pattern =
-      Pattern.compile("^" + JarDeployer.JAR_PREFIX + "DeployCommandsDUnit.*#\\d++$");
-  private File newDeployableJarFile;
-  private transient ClassBuilder classBuilder;
-  private transient CommandProcessor commandProcessor;
-
-  @Override
-  public final void postSetUpCliCommandTestBase() throws Exception {
-    this.newDeployableJarFile = new File(this.temporaryFolder.getRoot().getCanonicalPath()
-        + File.separator + "DeployCommandsDUnit1.jar");
-    this.classBuilder = new ClassBuilder();
-    this.commandProcessor = new CommandProcessor();
-    assertFalse(this.commandProcessor.isStopped());
-
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      public void run() {
-        deleteSavedJarFiles();
-      }
-    });
-    deleteSavedJarFiles();
+public class DeployCommandsDUnitTest implements Serializable {
+  private static final String GROUP1 = "Group1";
+  private static final String GROUP2 = "Group2";
+
+  private final String class1 = "DeployCommandsDUnitA";
+  private final String class2 = "DeployCommandsDUnitB";
+  private final String class3 = "DeployCommandsDUnitC";
+  private final String class4 = "DeployCommandsDUnitD";
+
+  private final String jarName1 = "DeployCommandsDUnit1.jar";
+  private final String jarName2 = "DeployCommandsDUnit2.jar";
+  private final String jarName3 = "DeployCommandsDUnit3.jar";
+  private final String jarName4 = "DeployCommandsDUnit4.jar";
+
+  private File jar1;
+  private File jar2;
+  private File jar3;
+  private File jar4;
+  private File subdirWithJars3and4;
+
+  private MemberVM locator;
+  private MemberVM server1;
+  private MemberVM server2;
+
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Rule
+  public transient GfshShellConnectionRule gfshConnector = new GfshShellConnectionRule();
+
+  @Before
+  public void setup() throws Exception {
+    ClassBuilder classBuilder = new ClassBuilder();
+    File jarsDir = lsRule.getTempFolder().newFolder();
+    jar1 = new File(jarsDir, jarName1);
+    jar2 = new File(jarsDir, jarName2);
+
+    subdirWithJars3and4 = new File(jarsDir, "subdir");
+    subdirWithJars3and4.mkdirs();
+    jar3 = new File(subdirWithJars3and4, jarName3);
+    jar4 = new File(subdirWithJars3and4, jarName4);
+
+    classBuilder.writeJarFromName(class1, jar1);
+    classBuilder.writeJarFromName(class2, jar2);
+    classBuilder.writeJarFromName(class3, jar3);
+    classBuilder.writeJarFromName(class4, jar4);
+
+    locator = lsRule.startLocatorVM(0);
+
+    Properties props = new Properties();
+    props.setProperty(GROUPS, GROUP1);
+    server1 = lsRule.startServerVM(1, props, locator.getPort());
+
+    props.setProperty(GROUPS, GROUP2);
+    server2 = lsRule.startServerVM(2, props, locator.getPort());
+
+    gfshConnector.connectAndVerify(locator);
   }
 
-  @SuppressWarnings("serial")
-  @Override
-  protected final void preTearDownCliCommandTestBase() throws Exception {
-    Host.getHost(0).getVM(1).invoke(new SerializableRunnable() {
-      public void run() {
-        DistributionManager.isDedicatedAdminVM = false;
-      }
-    });
+  @Test
+  public void deployJarToOneGroup() throws Exception {
+    // Deploy a jar to a single group
+    CommandResult cmdResult =
+        gfshConnector.executeAndVerifyCommand("deploy --jar=" + jar2 + " --group=" + GROUP1);
+    String resultString = commandResultToString(cmdResult);
 
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      public void run() {
-        deleteSavedJarFiles();
-      }
-    });
-    deleteSavedJarFiles();
+    assertThat(resultString).contains(server1.getName());
+    assertThat(resultString).doesNotContain(server2.getName());
+    assertThat(resultString).contains(jarName2);
+
+    server1.invoke(() -> assertThatCanLoad(jarName2, class2));
+    server2.invoke(() -> assertThatCannotLoad(jarName2, class2));
   }
 
   @Test
-  public void testDeploy() throws Exception {
-    final Properties props = new Properties();
-    final Host host = Host.getHost(0);
-    final VM vm = host.getVM(0);
-    final String vmName = "VM" + vm.getPid();
-
-    // Create the cache in this VM
-    props.setProperty(NAME, "Controller");
-    props.setProperty(GROUPS, "Group1");
-    getSystem(props);
-    getCache();
-
-    // Create the cache in the other VM
-    vm.invoke(new SerializableRunnable() {
-      public void run() {
-        props.setProperty(NAME, vmName);
-        props.setProperty(GROUPS, "Group2");
-        getSystem(props);
-        getCache();
-      }
+  public void deployMultipleJarsToOneGroup() throws Exception {
+    // Deploy of multiple JARs to a single group
+    CommandResult cmdResult = gfshConnector.executeAndVerifyCommand(
+        "deploy --group=" + GROUP1 + " --dir=" + subdirWithJars3and4.getCanonicalPath());
+    String resultString = commandResultToString(cmdResult);
+
+    assertThat(resultString).describedAs(resultString).contains(server1.getName());
+    assertThat(resultString).doesNotContain(server2.getName());
+    assertThat(resultString).contains(jarName3);
+    assertThat(resultString).contains(jarName4);
+
+    server1.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
     });
 
-    DeployCommands deployCommands = new DeployCommands();
-
-    // Single JAR all members
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit1.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitA")});
-    Result result = deployCommands.deploy(null, "DeployCommandsDUnit1.jar", null);
-
-    assertEquals(true, result.hasNextLine());
-
-    String resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(1, countMatchesInString(resultString, "Controller"));
-    assertEquals(1, countMatchesInString(resultString, vmName));
-    assertEquals(4, countMatchesInString(resultString, "DeployCommandsDUnit1.jar"));
-
-    // Single JAR with group
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit2.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitB")});
-    result = deployCommands.deploy(new String[] {"Group2"}, "DeployCommandsDUnit2.jar", null);
-
-    assertEquals(true, result.hasNextLine());
-
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(false, resultString.contains("Controller"));
-    assertEquals(1, countMatchesInString(resultString, vmName));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit2.jar"));
-
-    // Multiple JARs to all members
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit3.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitC"),
-        "DeployCommandsDUnit4.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitD")});
-    result = deployCommands.deploy(null, null, "AnyDirectory");
-
-    assertEquals(true, result.hasNextLine());
-
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(2, countMatchesInString(resultString, "Controller"));
-    assertEquals(2, countMatchesInString(resultString, vmName));
-    assertEquals(4, countMatchesInString(resultString, "DeployCommandsDUnit3.jar"));
-    assertEquals(4, countMatchesInString(resultString, "DeployCommandsDUnit4.jar"));
-
-    // Multiple JARs to a group
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit5.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitE"),
-        "DeployCommandsDUnit6.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitF")});
-    result = deployCommands.deploy(new String[] {"Group1"}, null, "AnyDirectory");
-
-    assertEquals(true, result.hasNextLine());
-
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(2, countMatchesInString(resultString, "Controller"));
-    assertEquals(false, resultString.contains(vmName));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit5.jar"));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit6.jar"));
-  }
 
-  @Test
-  public void testUndeploy() throws Exception {
-    final Properties props = new Properties();
-    final Host host = Host.getHost(0);
-    final VM vm = host.getVM(0);
-    final String vmName = "VM" + vm.getPid();
-
-    // Create the cache in this VM
-    props.setProperty(NAME, "Controller");
-    props.setProperty(GROUPS, "Group1");
-    getSystem(props);
-    getCache();
-
-    // Create the cache in the other VM
-    vm.invoke(new SerializableRunnable() {
-      public void run() {
-        props.setProperty(NAME, vmName);
-        props.setProperty(GROUPS, "Group2");
-        getSystem(props);
-        getCache();
-      }
+    // Undeploy of multiple jars by specifying group
+    gfshConnector.executeAndVerifyCommand("undeploy --group=" + GROUP1);
+    server1.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
     });
-
-    DeployCommands deployCommands = new DeployCommands();
-
-    // Deploy a couple of JAR files which can be undeployed
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit1.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitA")});
-    deployCommands.deploy(new String[] {"Group1"}, "DeployCommandsDUnit1.jar", null);
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit2.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitB")});
-    deployCommands.deploy(new String[] {"Group2"}, "DeployCommandsDUnit2.jar", null);
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit3.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitC")});
-    deployCommands.deploy(null, "DeployCommandsDUnit3.jar", null);
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit4.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitD")});
-    deployCommands.deploy(null, "DeployCommandsDUnit4.jar", null);
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit5.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitE")});
-    deployCommands.deploy(null, "DeployCommandsDUnit5.jar", null);
-
-    // Undeploy for 1 group
-    Result result = deployCommands.undeploy(new String[] {"Group1"}, "DeployCommandsDUnit1.jar");
-    assertEquals(true, result.hasNextLine());
-    String resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(1, countMatchesInString(resultString, "Controller"));
-    assertEquals(false, resultString.contains(vmName));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit1.jar"));
-
-    // Multiple Undeploy for all members
-    result = deployCommands.undeploy(null, "DeployCommandsDUnit2.jar, DeployCommandsDUnit3.jar");
-    assertEquals(true, result.hasNextLine());
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(2, countMatchesInString(resultString, "Controller"));
-    assertEquals(2, countMatchesInString(resultString, vmName));
-    assertEquals(3, countMatchesInString(resultString, "DeployCommandsDUnit2.jar"));
-    assertEquals(4, countMatchesInString(resultString, "DeployCommandsDUnit3.jar"));
-
-    // Undeploy all (no JAR specified)
-    result = deployCommands.undeploy(null, null);
-    assertEquals(true, result.hasNextLine());
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(2, countMatchesInString(resultString, "Controller"));
-    assertEquals(2, countMatchesInString(resultString, vmName));
-    assertEquals(4, countMatchesInString(resultString, "DeployCommandsDUnit4.jar"));
-    assertEquals(4, countMatchesInString(resultString, "DeployCommandsDUnit5.jar"));
   }
 
   @Test
-  public void testListDeployed() throws Exception {
-    final Properties props = new Properties();
-    final Host host = Host.getHost(0);
-    final VM vm = host.getVM(0);
-    final String vmName = "VM" + vm.getPid();
-
-    // Create the cache in this VM
-    props.setProperty(NAME, "Controller");
-    props.setProperty(GROUPS, "Group1");
-    getSystem(props);
-    getCache();
-
-    // Create the cache in the other VM
-    vm.invoke(new SerializableRunnable() {
-      public void run() {
-        props.setProperty(NAME, vmName);
-        props.setProperty(GROUPS, "Group2");
-        getSystem(props);
-        getCache();
-      }
-    });
-
-    DeployCommands deployCommands = new DeployCommands();
-
-    // Deploy a couple of JAR files which can be listed
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit1.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitA")});
-    deployCommands.deploy(new String[] {"Group1"}, "DeployCommandsDUnit1.jar", null);
-    CommandExecutionContext.setBytesFromShell(new byte[][] {"DeployCommandsDUnit2.jar".getBytes(),
-        this.classBuilder.createJarFromName("DeployCommandsDUnitB")});
-    deployCommands.deploy(new String[] {"Group2"}, "DeployCommandsDUnit2.jar", null);
-
-    // List for all members
-    Result result = deployCommands.listDeployed(null);
-    assertEquals(true, result.hasNextLine());
-    String resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(1, countMatchesInString(resultString, "Controller"));
-    assertEquals(1, countMatchesInString(resultString, vmName));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit1.jar"));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit2.jar"));
-
-    // List for members in Group1
-    result = deployCommands.listDeployed("Group1");
-    assertEquals(true, result.hasNextLine());
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(1, countMatchesInString(resultString, "Controller"));
-    assertEquals(false, resultString.contains(vmName));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit1.jar"));
-    assertEquals(false, resultString.contains("DeployCommandsDUnit2.jar"));
-
-    // List for members in Group2
-    result = deployCommands.listDeployed("Group2");
-    assertEquals(true, result.hasNextLine());
-    resultString = result.nextLine();
-    assertEquals(false, resultString.contains("ERROR"));
-    assertEquals(false, resultString.contains("Controller"));
-    assertEquals(1, countMatchesInString(resultString, vmName));
-    assertEquals(false, resultString.contains("DeployCommandsDUnit1.jar"));
-    assertEquals(2, countMatchesInString(resultString, "DeployCommandsDUnit2.jar"));
+  public void deployJarToAllServers() throws Exception {
+    // Deploy a jar to all servers
+    CommandResult cmdResult = gfshConnector.executeAndVerifyCommand("deploy --jar=" + jar1);
+
+    String resultString = commandResultToString(cmdResult);
+    assertThat(resultString).contains(server1.getName());
+    assertThat(resultString).contains(server2.getName());
+    assertThat(resultString).contains(jarName1);
+
+    server1.invoke(() -> assertThatCanLoad(jarName1, class1));
+    server2.invoke(() -> assertThatCanLoad(jarName1, class1));
+
+    // Undeploy of jar by specifying group
+    gfshConnector.executeAndVerifyCommand("undeploy --group=" + GROUP1);
+    server1.invoke(() -> assertThatCannotLoad(jarName1, class1));
+    server2.invoke(() -> assertThatCanLoad(jarName1, class1));
   }
 
-  /**
-   * Does an end-to-end test using the complete CLI framework while ensuring that the shared
-   * configuration is updated.
-   */
   @Test
-  public void testEndToEnd() throws Exception {
-    final String groupName = getName();
-    final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
-    jmxPort = ports[0];
-    httpPort = ports[1];
-    try {
-      jmxHost = InetAddress.getLocalHost().getHostName();
-    } catch (UnknownHostException ignore) {
-      jmxHost = "localhost";
-    }
+  public void deployMultipleJarsToAllServers() throws Exception {
+    gfshConnector.executeAndVerifyCommand("deploy --dir=" + subdirWithJars3and4.getCanonicalPath());
 
-    // Start the Locator and wait for shared configuration to be available
-    final int locatorPort = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET);
-    final String locatorLogPath = this.temporaryFolder.getRoot().getCanonicalPath() + File.separator
-        + "locator-" + locatorPort + ".log";
-
-    final Properties locatorProps = new Properties();
-    locatorProps.setProperty(NAME, "Locator");
-    locatorProps.setProperty(MCAST_PORT, "0");
-    locatorProps.setProperty(LOG_LEVEL, "fine");
-    locatorProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "true");
-    locatorProps.setProperty(JMX_MANAGER, "true");
-    locatorProps.setProperty(JMX_MANAGER_START, "true");
-    locatorProps.setProperty(JMX_MANAGER_BIND_ADDRESS, String.valueOf(jmxHost));
-    locatorProps.setProperty(JMX_MANAGER_PORT, String.valueOf(jmxPort));
-    locatorProps.setProperty(HTTP_SERVICE_PORT, String.valueOf(httpPort));
-
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        final File locatorLogFile = new File(locatorLogPath);
-        try {
-          final InternalLocator locator = (InternalLocator) Locator.startLocatorAndDS(locatorPort,
-              locatorLogFile, null, locatorProps);
-
-          WaitCriterion wc = new WaitCriterion() {
-            @Override
-            public boolean done() {
-              return locator.isSharedConfigurationRunning();
-            }
-
-            @Override
-            public String description() {
-              return "Waiting for shared configuration to be started";
-            }
-          };
-          Wait.waitForCriterion(wc, 5000, 500, true);
-
-        } catch (IOException e) {
-          fail("Unable to create a locator with a shared configuration", e);
-        }
-      }
+    server1.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
     });
 
-    connect(jmxHost, jmxPort, httpPort, getDefaultShell());
+    gfshConnector.executeAndVerifyCommand("undeploy");
 
-    Host.getHost(0).getVM(1).invoke(() -> {
-      Properties properties = new Properties();
-      properties.setProperty("name", "Manager");
-      properties.setProperty("groups", groupName);
-      ServerStarterRule serverStarterRule = new ServerStarterRule();
-      serverStarterRule.withProperties(properties).withConnectionToLocator(locatorPort)
-          .startServer();
+    server1.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
     });
+  }
 
-    // Create a JAR file
-    this.classBuilder.writeJarFromName("DeployCommandsDUnitA", this.newDeployableJarFile);
+  @Test
+  public void undeployOfMultipleJars() throws Exception {
+    gfshConnector.executeAndVerifyCommand("deploy --dir=" + subdirWithJars3and4.getCanonicalPath());
 
-    // Deploy the JAR
-    CommandResult cmdResult =
-        executeCommand("deploy --jar=" + this.newDeployableJarFile.getCanonicalPath());
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-
-    String stringResult = commandResultToString(cmdResult);
-    assertEquals(3, countLinesInString(stringResult, false));
-    assertTrue(stringContainsLine(stringResult, "Member.*JAR.*JAR Location"));
-    assertTrue(stringContainsLine(stringResult, "Manager.*DeployCommandsDUnit1.jar.*"
-        + JarDeployer.JAR_PREFIX + "DeployCommandsDUnit1.jar#1"));
-
-    // Undeploy the JAR
-    cmdResult = executeCommand("undeploy --jar=DeployCommandsDUnit1.jar");
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-
-    stringResult = commandResultToString(cmdResult);
-    assertEquals(3, countLinesInString(stringResult, false));
-    assertThat(stringContainsLine(stringResult, "Member.*JAR.*Un-Deployed From JAR Location"))
-        .describedAs(stringResult).isTrue();
-    assertThat(stringContainsLine(stringResult, "Manager.*DeployCommandsDUnit1.jar.*"
-        + JarDeployer.JAR_PREFIX + "DeployCommandsDUnit1.jar#1")).describedAs(stringResult)
-            .isTrue();;
-
-
-    // Deploy the JAR to a group
-    cmdResult = executeCommand(
-        "deploy --jar=" + this.newDeployableJarFile.getCanonicalPath() + " --group=" + groupName);
-    assertThat(cmdResult.getStatus()).describedAs(cmdResult.toString()).isEqualTo(Result.Status.OK);
-
-    stringResult = commandResultToString(cmdResult);
-    assertEquals(3, countLinesInString(stringResult, false));
-    assertThat(stringContainsLine(stringResult, "Member.*JAR.*JAR Location"))
-        .describedAs(stringResult).isTrue();
-
-    assertThat(stringContainsLine(stringResult, "Manager.*DeployCommandsDUnit1.jar.*"
-        + JarDeployer.JAR_PREFIX + "DeployCommandsDUnit1.jar#1")).describedAs(stringResult)
-            .isTrue();
-
-    // Make sure the deployed jar in the shared config
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        ClusterConfigurationService sharedConfig =
-            ((InternalLocator) Locator.getLocator()).getSharedConfiguration();
-        try {
-          assertTrue(sharedConfig.getConfiguration(groupName).getJarNames()
-              .contains("DeployCommandsDUnit1.jar"));
-        } catch (Exception e) {
-          Assert.fail("Error occurred in cluster configuration service", e);
-        }
-      }
+    server1.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
+    });
+    server2.invoke(() -> {
+      assertThatCanLoad(jarName3, class3);
+      assertThatCanLoad(jarName4, class4);
     });
 
-    // List deployed for group
-    cmdResult = executeCommand("list deployed --group=" + groupName);
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-
-    stringResult = commandResultToString(cmdResult);
-    assertEquals(3, countLinesInString(stringResult, false));
-    assertTrue(stringContainsLine(stringResult, "Member.*JAR.*JAR Location"));
-    assertTrue(stringContainsLine(stringResult, "Manager.*DeployCommandsDUnit1.jar.*"
-        + JarDeployer.JAR_PREFIX + "DeployCommandsDUnit1.jar#1"));
-
-    // Undeploy for group
-    cmdResult = executeCommand("undeploy --group=" + groupName);
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-
-    stringResult = commandResultToString(cmdResult);
-    assertEquals(3, countLinesInString(stringResult, false));
-    assertTrue(stringContainsLine(stringResult, "Member.*JAR.*Un-Deployed From JAR Location"));
-    assertTrue(stringContainsLine(stringResult, "Manager.*DeployCommandsDUnit1.jar.*"
-        + JarDeployer.JAR_PREFIX + "DeployCommandsDUnit1.jar#1"));
-
-    // Make sure the deployed jar was removed from the shared config
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      @Override
-      public void run() {
-        ClusterConfigurationService sharedConfig =
-            ((InternalLocator) Locator.getLocator()).getSharedConfiguration();
-        try {
-          assertFalse(sharedConfig.getConfiguration(groupName).getJarNames()
-              .contains("DeployCommandsDUnit1.jar"));
-        } catch (Exception e) {
-          Assert.fail("Error occurred in cluster configuration service", e);
-        }
-      }
+    gfshConnector
+        .executeAndVerifyCommand("undeploy --jars=" + jar3.getName() + "," + jar4.getName());
+    server1.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
     });
+    server2.invoke(() -> {
+      assertThatCannotLoad(jarName3, class3);
+      assertThatCannotLoad(jarName4, class4);
+    });
+  }
 
-    // List deployed with nothing deployed
-    cmdResult = executeCommand("list deployed");
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-    assertTrue(
-        commandResultToString(cmdResult).contains(CliStrings.LIST_DEPLOYED__NO_JARS_FOUND_MESSAGE));
+  private void assertThatCanLoad(String jarName, String className) throws ClassNotFoundException {
+    assertThat(ClassPathLoader.getLatest().getJarDeployer().findDeployedJar(jarName)).isNotNull();
+    assertThat(ClassPathLoader.getLatest().forName(className)).isNotNull();
   }
 
-  private void deleteSavedJarFiles() {
-    this.newDeployableJarFile.delete();
+  private void assertThatCannotLoad(String jarName, String className) {
+    assertThat(ClassPathLoader.getLatest().getJarDeployer().findDeployedJar(jarName)).isNull();
+    assertThatThrownBy(() -> ClassPathLoader.getLatest().forName(className))
+        .isExactlyInstanceOf(ClassNotFoundException.class);
+  }
 
-    File dirFile = new File(".");
 
-    // Find all deployed JAR files
-    File[] oldJarFiles = dirFile.listFiles(new FilenameFilter() {
-      @Override
-      public boolean accept(final File file, final String name) {
-        return DeployCommandsDUnitTest.this.pattern.matcher(name).matches();
-      }
-    });
+  @Test
+  public void testListDeployed() throws Exception {
+    // Deploy a couple of JAR files which can be listed
+    gfshConnector.executeAndVerifyCommand(
+        "deploy jar --group=" + GROUP1 + " --jar=" + jar1.getCanonicalPath());
+    gfshConnector.executeAndVerifyCommand(
+        "deploy jar --group=" + GROUP2 + " --jar=" + jar2.getCanonicalPath());
+
+    // List for all members
+    CommandResult commandResult = gfshConnector.executeAndVerifyCommand("list deployed");
+    String resultString = commandResultToString(commandResult);
+    assertThat(resultString).contains(server1.getName());
+    assertThat(resultString).contains(server2.getName());
+    assertThat(resultString).contains(jarName1);
+    assertThat(resultString).contains(jarName2);
+
+    // List for members in Group1
+    commandResult = gfshConnector.executeAndVerifyCommand("list deployed --group=" + GROUP1);
+    resultString = commandResultToString(commandResult);
+    assertThat(resultString).contains(server1.getName());
+    assertThat(resultString).doesNotContain(server2.getName());
+
+    assertThat(resultString).contains(jarName1);
+    assertThat(resultString).doesNotContain(jarName2);
+
+    // List for members in Group2
+    commandResult = gfshConnector.executeAndVerifyCommand("list deployed --group=" + GROUP2);
+    resultString = commandResultToString(commandResult);
+    assertThat(resultString).doesNotContain(server1.getName());
+    assertThat(resultString).contains(server2.getName());
+
+    assertThat(resultString).doesNotContain(jarName1);
+    assertThat(resultString).contains(jarName2);
+  }
 
-    // Now delete them
-    if (oldJarFiles != null) {
-      for (File oldJarFile : oldJarFiles) {
-        oldJarFile.delete();
-      }
+  protected static String commandResultToString(final CommandResult commandResult) {
+    assertNotNull(commandResult);
+    commandResult.resetToFirstLine();
+    StringBuilder buffer = new StringBuilder(commandResult.getHeader());
+    while (commandResult.hasNextLine()) {
+      buffer.append(commandResult.nextLine());
     }
+    buffer.append(commandResult.getFooter());
+    return buffer.toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/6fd2d123/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/UserCommandsDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/UserCommandsDUnitTest.java b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/UserCommandsDUnitTest.java
deleted file mode 100644
index 24f5cdb..0000000
--- a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/UserCommandsDUnitTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.geode.management.internal.cli.commands;
-
-import static org.apache.geode.test.dunit.Assert.assertEquals;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.geode.distributed.ConfigurationProperties;
-import org.apache.geode.internal.ClassBuilder;
-import org.apache.geode.internal.ClassPathLoader;
-import org.apache.geode.management.cli.Result;
-import org.apache.geode.management.internal.cli.CommandManager;
-import org.apache.geode.management.internal.cli.result.CommandResult;
-import org.apache.geode.test.dunit.Host;
-import org.apache.geode.test.dunit.SerializableRunnable;
-import org.apache.geode.test.junit.categories.DistributedTest;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Properties;
-
-/**
- * Unit tests for configuring user commands.
- *
- * @since GemFire 8.0
- */
-@Category(DistributedTest.class)
-public class UserCommandsDUnitTest extends CliCommandTestBase {
-
-  private static final long serialVersionUID = 1L;
-  final File jarDirectory = new File((new File(
-      ClassPathLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath()))
-          .getParent(),
-      "ext");
-  final File jarFile = new File(this.jarDirectory, "UserCommandsDUnit.jar");
-  boolean deleteJarDirectory = false;
-
-  @Override
-  public final void postSetUpCliCommandTestBase() throws Exception {
-    createUserCommandJarFile();
-  }
-
-  @Override
-  public final void postTearDownCacheTestCase() throws Exception {
-    if (this.deleteJarDirectory) {
-      FileUtils.deleteDirectory(this.jarDirectory);
-    } else {
-      FileUtils.forceDelete(this.jarFile);
-    }
-
-    System.clearProperty(CommandManager.USER_CMD_PACKAGES_PROPERTY);
-    ClassPathLoader.setLatestToDefault();
-    CommandManager.clearInstance();
-
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      private static final long serialVersionUID = 1L;
-
-      @Override
-      public void run() {
-        System.clearProperty(CommandManager.USER_CMD_PACKAGES_PROPERTY);
-        ClassPathLoader.setLatestToDefault();
-        CommandManager.clearInstance();
-      }
-    });
-  }
-
-  public void createUserCommandJarFile() throws IOException {
-    this.deleteJarDirectory = this.jarDirectory.mkdir();
-
-    StringBuffer stringBuffer = new StringBuffer();
-
-    stringBuffer.append("package junit.ucdunit;");
-    stringBuffer.append("import org.springframework.shell.core.CommandMarker;");
-    stringBuffer
-        .append("import org.springframework.shell.core.annotation.CliAvailabilityIndicator;");
-    stringBuffer.append("import org.springframework.shell.core.annotation.CliCommand;");
-    stringBuffer.append("import org.springframework.shell.core.annotation.CliOption;");
-    stringBuffer.append("import org.apache.geode.management.cli.Result;");
-    stringBuffer.append("import org.apache.geode.management.internal.cli.CliUtil;");
-    stringBuffer.append("import org.apache.geode.management.internal.cli.result.ResultBuilder;");
-    stringBuffer.append("import org.apache.geode.management.internal.cli.shell.Gfsh;");
-
-    stringBuffer.append(
-        "public final class UCDunitClass implements CommandMarker { public UCDunitClass() {}");
-    stringBuffer.append("@CliCommand(value = { \"ucdunitcmd\" }, help = \"ucdunitcmd help\")");
-    stringBuffer.append(
-        "public final Result ucdunitcmd(@CliOption(key = { \"name\" }, help = \"ucdunitcmd name help\") String name) {");
-    stringBuffer.append("return ResultBuilder.createInfoResult(\"ucdunitcmd \" + name); }");
-    stringBuffer.append("@CliAvailabilityIndicator({ \"ucdunitcmd\" })");
-    stringBuffer.append("public final boolean isAvailable() { return true; } }");
-
-    ClassBuilder classBuilder = new ClassBuilder();
-    final byte[] jarBytes = classBuilder.createJarFromClassContent("junit/ucdunit/UCDunitClass",
-        stringBuffer.toString());
-
-    final FileOutputStream outStream = new FileOutputStream(this.jarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-  }
-
-  @Test
-  public void testCommandLineProperty() {
-    System.setProperty(CommandManager.USER_CMD_PACKAGES_PROPERTY, "junit.ucdunit");
-
-    ClassPathLoader.setLatestToDefault();
-    CommandManager.clearInstance();
-
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      private static final long serialVersionUID = 1L;
-
-      @Override
-      public void run() {
-        System.setProperty(CommandManager.USER_CMD_PACKAGES_PROPERTY, "junit.ucdunit");
-        ClassPathLoader.setLatestToDefault();
-        CommandManager.clearInstance();
-      }
-    });
-
-    setUpJmxManagerOnVm0ThenConnect(null);
-
-    CommandResult cmdResult = executeCommand("ucdunitcmd");
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-  }
-
-  @Test
-  public void testGemFireProperty() {
-    System.setProperty(CommandManager.USER_CMD_PACKAGES_PROPERTY, "junit.ucdunit");
-
-    ClassPathLoader.setLatestToDefault();
-    CommandManager.clearInstance();
-
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      private static final long serialVersionUID = 1L;
-
-      @Override
-      public void run() {
-        ClassPathLoader.setLatestToDefault();
-        CommandManager.clearInstance();
-      }
-    });
-
-    Properties properties = new Properties();
-    properties.setProperty(ConfigurationProperties.USER_COMMAND_PACKAGES, "junit.ucdunit");
-    setUpJmxManagerOnVm0ThenConnect(properties);
-
-    CommandResult cmdResult = executeCommand("ucdunitcmd");
-    assertEquals(Result.Status.OK, cmdResult.getStatus());
-  }
-}