geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jstew...@apache.org
Subject [2/7] geode git commit: GEODE-2325: Improve tests for JarDeployer
Date Tue, 28 Feb 2017 23:37:45 GMT
http://git-wip-us.apache.org/repos/asf/geode/blob/228bf4ff/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
new file mode 100644
index 0000000..3e3e68b
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/DeployedJarJUnitTest.java
@@ -0,0 +1,750 @@
+/*
+ * 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.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
+import static org.apache.geode.internal.JarDeployer.JAR_PREFIX;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.internal.cache.execute.FunctionContextImpl;
+import org.apache.geode.test.junit.categories.IntegrationTest;
+import org.junit.After;
+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.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * TODO: Need to fix this testDeclarableFunctionsWithParms and testClassOnClasspath on Windows:
+ */
+@Category(IntegrationTest.class)
+public class DeployedJarJUnitTest {
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+  @Rule
+  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
+
+  private final ClassBuilder classBuilder = new ClassBuilder();
+
+  private InternalCache cache;
+
+  @Before
+  public void setup() throws IOException {
+    System.setProperty("user.dir", temporaryFolder.newFolder().getAbsolutePath());
+    ClassPathLoader.setLatestToDefault();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    ClassPathLoader.setLatestToDefault();
+    for (String functionName : FunctionService.getRegisteredFunctions().keySet()) {
+      if (functionName.startsWith("JarClassLoaderJUnit")) {
+        FunctionService.unregisterFunction(functionName);
+      }
+    }
+
+    if (this.cache != null) {
+      this.cache.close();
+    }
+  }
+
+  @Test
+  public void testIsValidJarContent() throws IOException {
+    assertTrue(
+        DeployedJar.isValidJarContent(this.classBuilder.createJarFromName("JarClassLoaderJUnitA")));
+  }
+
+  @Test
+  public void testIsInvalidJarContent() {
+    assertFalse(DeployedJar.isValidJarContent("INVALID JAR CONTENT".getBytes()));
+  }
+
+  @Test
+  public void testClassOnClasspath() throws Exception {
+    // Deploy the first JAR file and make sure the class is on the Classpath
+    byte[] jarBytes =
+        this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitA",
+            "package com.jcljunit; public class JarClassLoaderJUnitA {}");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
+
+    try {
+      ClassPathLoader.getLatest().forName("com.jcljunit.JarClassLoaderJUnitA");
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath");
+    }
+
+    // Update the JAR file and make sure the first class is no longer on the Classpath
+    // and the second one is.
+    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
+        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
+
+    try {
+      ClassPathLoader.getLatest().forName("com.jcljunit.JarClassLoaderJUnitB");
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath");
+    }
+
+    try {
+      ClassPathLoader.getLatest().forName("com.jcljunit.JarClassLoaderJUnitA");
+      fail("Class should not be found on Classpath");
+    } catch (ClassNotFoundException expected) { // expected
+    }
+
+  }
+
+  @Test
+  public void testFailingCompilation() throws Exception {
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("import org.apache.geode.cache.Declarable;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer.append("public class JarClassLoaderJUnitFunction implements Function {}");
+    String functionString = stringBuffer.toString();
+
+    try {
+      this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+      fail("This code should have failed to compile and thrown an exception");
+    } catch (Exception ex) {
+      // All good
+    }
+  }
+
+  @Test
+  public void testFunctions() throws IOException, ClassNotFoundException {
+    // Test creating a JAR file with a function
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("import java.util.Properties;");
+    stringBuffer.append("import org.apache.geode.cache.Declarable;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer.append("public class JarClassLoaderJUnitFunction implements Function {");
+    stringBuffer.append("public void init(Properties props) {}");
+    stringBuffer.append("public boolean hasResult() {return true;}");
+    stringBuffer.append(
+        "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"GOODv1\");}");
+    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}");
+    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
+    stringBuffer.append("public boolean isHA() {return false;}}");
+    String functionString = stringBuffer.toString();
+
+    byte[] jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
+
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertNotNull(function);
+    TestResultSender resultSender = new TestResultSender();
+    FunctionContext functionContext = new FunctionContextImpl(function.getId(), null, resultSender);
+    function.execute(functionContext);
+    assertEquals("GOODv1", (String) resultSender.getResults());
+
+    // Test updating the function with a new JAR file
+    functionString = functionString.replace("v1", "v2");
+    jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
+
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertNotNull(function);
+    resultSender = new TestResultSender();
+    functionContext = new FunctionContextImpl(function.getId(), null, resultSender);
+    function.execute(functionContext);
+    assertEquals("GOODv2", (String) resultSender.getResults());
+
+    // Test returning null for the Id
+    String functionNullIdString =
+        functionString.replace("return \"JarClassLoaderJUnitFunction\"", "return null");
+    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction",
+        functionNullIdString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnit.jar", jarBytes);
+
+    assertNull(FunctionService.getFunction("JarClassLoaderJUnitFunction"));
+
+    // Test removing the JAR
+    ClassPathLoader.getLatest().getJarDeployer().undeploy("JarClassLoaderJUnit.jar");
+    assertNull(FunctionService.getFunction("JarClassLoaderJUnitFunction"));
+  }
+
+  /**
+   * Ensure that abstract functions aren't added to the Function Service.
+   */
+  @Test
+  public void testAbstractFunction() throws IOException, ClassNotFoundException {
+    // Add an abstract Function to the Classpath
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("public abstract class JarClassLoaderJUnitFunction implements Function {");
+    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}}");
+    String functionString = stringBuffer.toString();
+
+    byte[] jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    try {
+      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath");
+    }
+
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertNull(function);
+  }
+
+  @Test
+  public void testDeclarableFunctionsWithNoCacheXml() throws IOException, ClassNotFoundException {
+    final String jarName = "JarClassLoaderJUnitNoXml.jar";
+
+    // Add a Declarable Function without parameters for the class to the Classpath
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("import java.util.Properties;");
+    stringBuffer.append("import org.apache.geode.cache.Declarable;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer
+        .append("public class JarClassLoaderJUnitFunctionNoXml implements Function, Declarable {");
+    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunctionNoXml\";}");
+    stringBuffer.append("public void init(Properties props) {}");
+    stringBuffer.append(
+        "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"NOPARMSv1\");}");
+    stringBuffer.append("public boolean hasResult() {return true;}");
+    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
+    stringBuffer.append("public boolean isHA() {return false;}}");
+    String functionString = stringBuffer.toString();
+
+    byte[] jarBytes = this.classBuilder
+        .createJarFromClassContent("JarClassLoaderJUnitFunctionNoXml", functionString);
+
+    ClassPathLoader.getLatest().getJarDeployer().deploy(jarName, jarBytes);
+
+    try {
+      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunctionNoXml");
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath");
+    }
+
+    // Check to see if the function without parameters executes correctly
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunctionNoXml");
+    assertNotNull(function);
+    TestResultSender resultSender = new TestResultSender();
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("NOPARMSv1", (String) resultSender.getResults());
+  }
+
+  @Test
+  public void testDeclarableFunctionsWithoutParms() throws IOException, ClassNotFoundException {
+    final File jarFile1 = new File("JarClassLoaderJUnit.v1.jar");
+    final File jarFile2 = new File("JarClassLoaderJUnit.v2.jar");
+
+    Properties properties = new Properties();
+    properties.setProperty(MCAST_PORT, "0");
+    CacheFactory cacheFactory = new CacheFactory(properties);
+    this.cache = (InternalCache) cacheFactory.create();
+
+    // Add a Declarable Function without parameters for the class to the Classpath
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("import java.util.Properties;");
+    stringBuffer.append("import org.apache.geode.cache.Declarable;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer
+        .append("public class JarClassLoaderJUnitFunction implements Function, Declarable {");
+    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}");
+    stringBuffer.append("public void init(Properties props) {}");
+    stringBuffer.append(
+        "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"NOPARMSv1\");}");
+    stringBuffer.append("public boolean hasResult() {return true;}");
+    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
+    stringBuffer.append("public boolean isHA() {return false;}}");
+    String functionString = stringBuffer.toString();
+
+    byte[] jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    try {
+      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath");
+    }
+
+    // Create a cache.xml file and configure the cache with it
+    stringBuffer = new StringBuffer();
+    stringBuffer.append("<?xml version=\"1.0\"?>");
+    stringBuffer.append("<!DOCTYPE cache PUBLIC");
+    stringBuffer.append("  \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
+    stringBuffer.append("  \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
+    stringBuffer.append("<cache>");
+    stringBuffer.append("  <function-service>");
+    stringBuffer.append("    <function>");
+    stringBuffer.append("      <class-name>JarClassLoaderJUnitFunction</class-name>");
+    stringBuffer.append("    </function>");
+    stringBuffer.append(" </function-service>");
+    stringBuffer.append("</cache>");
+    String cacheXmlString = stringBuffer.toString();
+    this.cache.loadCacheXml(new ByteArrayInputStream(cacheXmlString.getBytes()));
+
+    // Check to see if the function without parameters executes correctly
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertNotNull(function);
+    TestResultSender resultSender = new TestResultSender();
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("NOPARMSv1", (String) resultSender.getResults());
+
+    // Update the second function (change the value returned from execute) by deploying a JAR file
+    functionString = functionString.replace("v1", "v2");
+    jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    // Check to see if the updated function without parameters executes correctly
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("NOPARMSv2", (String) resultSender.getResults());
+  }
+
+  @Test
+  public void testDeclarableFunctionsWithParms() throws IOException, ClassNotFoundException {
+
+    Properties properties = new Properties();
+    properties.setProperty(MCAST_PORT, "0");
+    CacheFactory cacheFactory = new CacheFactory(properties);
+    this.cache = (InternalCache) cacheFactory.create();
+
+    // Add a Declarable Function with parameters to the class to the Classpath
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("import java.util.Properties;");
+    stringBuffer.append("import org.apache.geode.cache.Declarable;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer
+        .append("public class JarClassLoaderJUnitFunction implements Function, Declarable {");
+    stringBuffer.append("private Properties properties;");
+    stringBuffer.append(
+        "public String getId() {if(this.properties==null) {return \"JarClassLoaderJUnitFunction\";} else {return (String) this.properties.get(\"id\");}}");
+    stringBuffer.append("public void init(Properties props) {properties = props;}");
+    stringBuffer.append(
+        "public void execute(FunctionContext context) {context.getResultSender().lastResult(properties.get(\"returnValue\") + \"v1\");}");
+    stringBuffer.append("public boolean hasResult() {return true;}");
+    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
+    stringBuffer.append("public boolean isHA() {return false;}}");
+    String functionString = stringBuffer.toString();
+
+    byte[] jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    try {
+      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath");
+    }
+
+    // Create a cache.xml file and configure the cache with it
+    stringBuffer = new StringBuffer();
+    stringBuffer.append("<?xml version=\"1.0\"?>");
+    stringBuffer.append("<!DOCTYPE cache PUBLIC");
+    stringBuffer.append("  \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
+    stringBuffer.append("  \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
+    stringBuffer.append("<cache>");
+    stringBuffer.append("  <function-service>");
+    stringBuffer.append("    <function>");
+    stringBuffer.append("      <class-name>JarClassLoaderJUnitFunction</class-name>");
+    stringBuffer.append(
+        "      <parameter name=\"id\"><string>JarClassLoaderJUnitFunctionA</string></parameter>");
+    stringBuffer.append("      <parameter name=\"returnValue\"><string>DOG</string></parameter>");
+    stringBuffer.append("    </function>");
+    stringBuffer.append("    <function>");
+    stringBuffer.append("      <class-name>JarClassLoaderJUnitFunction</class-name>");
+    stringBuffer.append(
+        "      <parameter name=\"id\"><string>JarClassLoaderJUnitFunctionB</string></parameter>");
+    stringBuffer.append("      <parameter name=\"returnValue\"><string>CAT</string></parameter>");
+    stringBuffer.append("    </function>");
+    stringBuffer.append(" </function-service>");
+    stringBuffer.append("</cache>");
+    String cacheXmlString = stringBuffer.toString();
+    this.cache.loadCacheXml(new ByteArrayInputStream(cacheXmlString.getBytes()));
+
+    // Check to see if the functions with parameters execute correctly
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunctionA");
+    assertNotNull(function);
+    TestResultSender resultSender = new TestResultSender();
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("DOGv1", (String) resultSender.getResults());
+
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionB");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("CATv1", (String) resultSender.getResults());
+
+    // Update the first function (change the value returned from execute)
+    functionString = functionString.replace("v1", "v2");
+    jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    // Check to see if the updated functions with parameters execute correctly
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionA");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("DOGv2", (String) resultSender.getResults());
+
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionB");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("CATv2", (String) resultSender.getResults());
+
+    // Update cache xml to add a new function and replace an existing one
+    cacheXmlString =
+        cacheXmlString.replace("JarClassLoaderJUnitFunctionA", "JarClassLoaderJUnitFunctionC")
+            .replace("CAT", "BIRD");
+    this.cache.loadCacheXml(new ByteArrayInputStream(cacheXmlString.getBytes()));
+
+    // Update the first function (change the value returned from execute)
+    functionString = functionString.replace("v2", "v3");
+    jarBytes =
+        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+    // Check to see if the updated functions with parameters execute correctly
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionA");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("DOGv3", (String) resultSender.getResults());
+
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionC");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("DOGv3", (String) resultSender.getResults());
+
+    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionB");
+    assertNotNull(function);
+    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
+    assertEquals("BIRDv3", (String) resultSender.getResults());
+  }
+
+  @Test
+  public void testDependencyBetweenJars() throws IOException, ClassNotFoundException {
+    final File parentJarFile = temporaryFolder.newFile("JarClassLoaderJUnitParent.jar");
+    final File usesJarFile = temporaryFolder.newFile("JarClassLoaderJUnitUses.jar");
+
+    JarDeployer jarDeployer = ClassPathLoader.getLatest().getJarDeployer();
+
+    // Write out a JAR files.
+    StringBuffer stringBuffer = new StringBuffer();
+    stringBuffer.append("package jcljunit.parent;");
+    stringBuffer.append("public class JarClassLoaderJUnitParent {");
+    stringBuffer.append("public String getValueParent() {");
+    stringBuffer.append("return \"PARENT\";}}");
+
+    byte[] jarBytes = this.classBuilder.createJarFromClassContent(
+        "jcljunit/parent/JarClassLoaderJUnitParent", stringBuffer.toString());
+    writeJarBytesToFile(parentJarFile, jarBytes);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitParent.jar", jarBytes);
+
+    stringBuffer = new StringBuffer();
+    stringBuffer.append("package jcljunit.uses;");
+    stringBuffer.append("public class JarClassLoaderJUnitUses {");
+    stringBuffer.append("public String getValueUses() {");
+    stringBuffer.append("return \"USES\";}}");
+
+    jarBytes = this.classBuilder.createJarFromClassContent("jcljunit/uses/JarClassLoaderJUnitUses",
+        stringBuffer.toString());
+    writeJarBytesToFile(usesJarFile, jarBytes);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUses.jar", jarBytes);
+
+    stringBuffer = new StringBuffer();
+    stringBuffer.append("package jcljunit.function;");
+    stringBuffer.append("import jcljunit.parent.JarClassLoaderJUnitParent;");
+    stringBuffer.append("import jcljunit.uses.JarClassLoaderJUnitUses;");
+    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
+    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
+    stringBuffer.append(
+        "public class JarClassLoaderJUnitFunction  extends JarClassLoaderJUnitParent implements Function {");
+    stringBuffer.append("private JarClassLoaderJUnitUses uses = new JarClassLoaderJUnitUses();");
+    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 \"JarClassLoaderJUnitFunction\";}");
+    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(
+        "jcljunit/function/JarClassLoaderJUnitFunction", stringBuffer.toString());
+
+
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitFunction.jar",
+        jarBytes);
+
+
+    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
+    assertNotNull(function);
+    TestResultSender resultSender = new TestResultSender();
+    FunctionContext functionContext = new FunctionContextImpl(function.getId(), null, resultSender);
+    function.execute(functionContext);
+    assertEquals("PARENT:USES", (String) resultSender.getResults());
+  }
+
+  @Test
+  public void testFindResource() throws IOException, ClassNotFoundException {
+    final String fileName = "file.txt";
+    final String fileContent = "FILE CONTENT";
+
+    byte[] jarBytes = this.classBuilder.createJarFromFileContent(fileName, fileContent);
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitResource.jar",
+        jarBytes);
+
+    InputStream inputStream = ClassPathLoader.getLatest().getResourceAsStream(fileName);
+    assertNotNull(inputStream);
+
+    final byte[] fileBytes = new byte[fileContent.length()];
+    inputStream.read(fileBytes);
+    inputStream.close();
+    assertTrue(fileContent.equals(new String(fileBytes)));
+  }
+
+  @Test
+  public void testUpdateClassInJar() throws IOException, ClassNotFoundException {
+    // First use of the JAR file
+    byte[] jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
+        "public class JarClassLoaderJUnitTestClass { public Integer getValue5() { return new Integer(5); } }");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUpdate.jar", jarBytes);
+
+    try {
+      Class<?> clazz = ClassPathLoader.getLatest().forName("JarClassLoaderJUnitTestClass");
+      Object object = clazz.newInstance();
+      Method getValue5Method = clazz.getMethod("getValue5", new Class[] {});
+      Integer value = (Integer) getValue5Method.invoke(object, new Object[] {});
+      assertEquals(value.intValue(), 5);
+
+    } catch (InvocationTargetException itex) {
+      fail("JAR file not correctly added to Classpath" + itex);
+    } catch (NoSuchMethodException nsmex) {
+      fail("JAR file not correctly added to Classpath" + nsmex);
+    } catch (InstantiationException iex) {
+      fail("JAR file not correctly added to Classpath" + iex);
+    } catch (IllegalAccessException iaex) {
+      fail("JAR file not correctly added to Classpath" + iaex);
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath" + cnfex);
+    }
+
+    // Now create an updated JAR file and make sure that the method from the new
+    // class is available.
+    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
+        "public class JarClassLoaderJUnitTestClass { public Integer getValue10() { return new Integer(10); } }");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitUpdate.jar", jarBytes);
+
+
+    try {
+      Class<?> clazz = ClassPathLoader.getLatest().forName("JarClassLoaderJUnitTestClass");
+      Object object = clazz.newInstance();
+      Method getValue10Method = clazz.getMethod("getValue10", new Class[] {});
+      Integer value = (Integer) getValue10Method.invoke(object, new Object[] {});
+      assertEquals(value.intValue(), 10);
+
+    } catch (InvocationTargetException itex) {
+      fail("JAR file not correctly added to Classpath" + itex);
+    } catch (NoSuchMethodException nsmex) {
+      fail("JAR file not correctly added to Classpath" + nsmex);
+    } catch (InstantiationException iex) {
+      fail("JAR file not correctly added to Classpath" + iex);
+    } catch (IllegalAccessException iaex) {
+      fail("JAR file not correctly added to Classpath" + iaex);
+    } catch (ClassNotFoundException cnfex) {
+      fail("JAR file not correctly added to Classpath" + cnfex);
+    }
+  }
+
+  @Test
+  public void testMultiThread() throws IOException, ClassNotFoundException {
+    // Add two JARs to the classpath
+    byte[] jarBytes = this.classBuilder.createJarFromName("JarClassLoaderJUnitA");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitA.jar", jarBytes);
+
+    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
+        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
+    ClassPathLoader.getLatest().getJarDeployer().deploy("JarClassLoaderJUnitB.jar", jarBytes);
+
+    String[] classNames = new String[] {"JarClassLoaderJUnitA", "com.jcljunit.JarClassLoaderJUnitB",
+        "NON-EXISTENT CLASS"};
+
+    // Spawn some threads which try to instantiate these classes
+    final int threadCount = 10;
+    final int numLoops = 1000;
+    final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount + 1);
+    for (int i = 0; i < threadCount; i++) {
+      new ForNameExerciser(cyclicBarrier, numLoops, classNames).start();
+    }
+
+    // Wait for all of the threads to be ready
+    try {
+      cyclicBarrier.await();
+    } catch (InterruptedException iex) {
+      fail("Interrupted while waiting for barrier");
+    } catch (BrokenBarrierException bbex) {
+      fail("Broken barrier while waiting");
+    }
+
+    // Loop while each thread tries N times to instantiate a non-existent class
+    for (int i = 0; i < numLoops; i++) {
+      try {
+        cyclicBarrier.await(5, TimeUnit.SECONDS);
+      } catch (InterruptedException iex) {
+        fail("Interrupted while waiting for barrier");
+      } catch (TimeoutException tex) {
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+        long[] threadIds = threadMXBean.findDeadlockedThreads();
+
+        if (threadIds != null) {
+          StringBuffer deadLockTrace = new StringBuffer();
+          for (long threadId : threadIds) {
+            ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId, 100);
+            deadLockTrace.append(threadInfo.getThreadName()).append("\n");
+            for (StackTraceElement stackTraceElem : threadInfo.getStackTrace()) {
+              deadLockTrace.append("\t").append(stackTraceElem).append("\n");
+            }
+          }
+
+          fail("Deadlock with trace:\n" + deadLockTrace.toString());
+        }
+
+        fail("Timeout while waiting for barrier - no deadlock detected");
+      } catch (BrokenBarrierException bbex) {
+        fail("Broken barrier while waiting");
+      }
+    }
+  }
+
+
+  private void writeJarBytesToFile(File jarFile, byte[] jarBytes) throws IOException {
+    final OutputStream outStream = new FileOutputStream(jarFile);
+    outStream.write(jarBytes);
+    outStream.close();
+  }
+
+  private static class TestResultSender implements ResultSender<Object> {
+    private Object result;
+
+    public TestResultSender() {}
+
+    protected Object getResults() {
+      return this.result;
+    }
+
+    @Override
+    public void lastResult(final Object lastResult) {
+      this.result = lastResult;
+    }
+
+    @Override
+    public void sendResult(final Object oneResult) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void sendException(final Throwable t) {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  static final Random random = new Random();
+
+  private class ForNameExerciser extends Thread {
+    private final CyclicBarrier cyclicBarrier;
+    private final int numLoops;
+    private final String[] classNames;
+
+    ForNameExerciser(final CyclicBarrier cyclicBarrier, final int numLoops,
+        final String[] classNames) {
+      this.cyclicBarrier = cyclicBarrier;
+      this.numLoops = numLoops;
+      this.classNames = classNames;
+    }
+
+    @Override
+    public void run() {
+      try {
+        this.cyclicBarrier.await();
+      } catch (InterruptedException iex) {
+        fail("Interrupted while waiting for latch");
+      } catch (BrokenBarrierException bbex) {
+        fail("Broken barrier while waiting");
+      }
+      for (int i = 0; i < this.numLoops; i++) {
+        try {
+          // Random select a name from the list of class names and try to load it
+          String className = this.classNames[random.nextInt(this.classNames.length)];
+          ClassPathLoader.getLatest().forName(className);
+        } catch (ClassNotFoundException expected) { // expected
+        }
+        try {
+          this.cyclicBarrier.await();
+        } catch (InterruptedException iex) {
+          fail("Interrupted while waiting for barrrier");
+        } catch (BrokenBarrierException bbex) {
+          fail("Broken barrier while waiting");
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/228bf4ff/geode-core/src/test/java/org/apache/geode/internal/JarClassLoaderJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/JarClassLoaderJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/JarClassLoaderJUnitTest.java
deleted file mode 100644
index adc1d2e..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/JarClassLoaderJUnitTest.java
+++ /dev/null
@@ -1,851 +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.apache.geode.distributed.ConfigurationProperties.*;
-import static org.junit.Assert.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Properties;
-import java.util.Random;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.regex.Pattern;
-
-import org.junit.After;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import org.apache.geode.cache.CacheFactory;
-import org.apache.geode.cache.execute.Function;
-import org.apache.geode.cache.execute.FunctionContext;
-import org.apache.geode.cache.execute.FunctionService;
-import org.apache.geode.cache.execute.ResultSender;
-import org.apache.geode.internal.cache.InternalCache;
-import org.apache.geode.internal.cache.execute.FunctionContextImpl;
-import org.apache.geode.test.junit.categories.IntegrationTest;
-
-/**
- * TODO: Need to fix this testDeclarableFunctionsWithParms and testClassOnClasspath on Windows:
- */
-@Category(IntegrationTest.class)
-public class JarClassLoaderJUnitTest {
-
-  private static final String JAR_PREFIX = "vf.gf#";
-
-  private final ClassBuilder classBuilder = new ClassBuilder();
-  final Pattern pattern = Pattern.compile("^" + JAR_PREFIX + "JarClassLoaderJUnit.*#\\d++$");
-
-  private InternalCache cache;
-
-  @After
-  public void tearDown() throws Exception {
-    for (ClassLoader classLoader : ClassPathLoader.getLatest().getClassLoaders()) {
-      if (classLoader instanceof JarClassLoader) {
-        JarClassLoader jarClassLoader = (JarClassLoader) classLoader;
-        if (jarClassLoader.getJarName().startsWith("JarClassLoaderJUnit")) {
-          ClassPathLoader.getLatest().removeAndSetLatest(jarClassLoader);
-        }
-      }
-    }
-    for (String functionName : FunctionService.getRegisteredFunctions().keySet()) {
-      if (functionName.startsWith("JarClassLoaderJUnit")) {
-        FunctionService.unregisterFunction(functionName);
-      }
-    }
-
-    if (this.cache != null) {
-      this.cache.close();
-    }
-
-    deleteSavedJarFiles();
-  }
-
-  @Test
-  public void testValidJarContent() throws IOException {
-    assertTrue(JarClassLoader
-        .isValidJarContent(this.classBuilder.createJarFromName("JarClassLoaderJUnitA")));
-  }
-
-  @Test
-  public void testInvalidJarContent() {
-    assertFalse(JarClassLoader.isValidJarContent("INVALID JAR CONTENT".getBytes()));
-  }
-
-  @Test
-  public void testClassOnClasspath() throws IOException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#1");
-    final File jarFile2 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#2");
-    ClassPathLoader classPathLoader = ClassPathLoader.createWithDefaults(false);
-
-    // Deploy the first JAR file and make sure the class is on the Classpath
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitA",
-            "package com.jcljunit; public class JarClassLoaderJUnitA {}");
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader = new JarClassLoader(jarFile1, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-
-    try {
-      classPathLoader.forName("com.jcljunit.JarClassLoaderJUnitA");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    // Update the JAR file and make sure the first class is no longer on the Classpath
-    // and the second one is.
-    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
-        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
-    writeJarBytesToFile(jarFile2, jarBytes);
-    classLoader = new JarClassLoader(jarFile2, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-
-    try {
-      classPathLoader.forName("com.jcljunit.JarClassLoaderJUnitB");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    try {
-      classPathLoader.forName("com.jcljunit.JarClassLoaderJUnitA");
-      fail("Class should not be found on Classpath");
-    } catch (ClassNotFoundException expected) { // expected
-    }
-
-    classPathLoader.remove(classLoader);
-  }
-
-  @Test
-  public void testFailingCompilation() throws Exception {
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("import org.apache.geode.cache.Declarable;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer.append("public class JarClassLoaderJUnitFunction implements Function {}");
-    String functionString = stringBuffer.toString();
-
-    try {
-      this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-      fail("This code should have failed to compile and thrown an exception");
-    } catch (Exception ex) {
-      // All good
-    }
-  }
-
-  @Test
-  public void testFunctions() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#1");
-    final File jarFile2 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#2");
-    ClassPathLoader classPathLoader = ClassPathLoader.createWithDefaults(false);
-
-    // Test creating a JAR file with a function
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("import java.util.Properties;");
-    stringBuffer.append("import org.apache.geode.cache.Declarable;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer.append("public class JarClassLoaderJUnitFunction implements Function {");
-    stringBuffer.append("public void init(Properties props) {}");
-    stringBuffer.append("public boolean hasResult() {return true;}");
-    stringBuffer.append(
-        "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"GOODv1\");}");
-    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}");
-    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
-    stringBuffer.append("public boolean isHA() {return false;}}");
-    String functionString = stringBuffer.toString();
-
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader = new JarClassLoader(jarFile1, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertNotNull(function);
-    TestResultSender resultSender = new TestResultSender();
-    FunctionContext functionContext = new FunctionContextImpl(function.getId(), null, resultSender);
-    function.execute(functionContext);
-    assertEquals("GOODv1", (String) resultSender.getResults());
-
-    // Test updating the function with a new JAR file
-    functionString = functionString.replace("v1", "v2");
-    jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile2, jarBytes);
-    classLoader = new JarClassLoader(jarFile2, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertNotNull(function);
-    resultSender = new TestResultSender();
-    functionContext = new FunctionContextImpl(function.getId(), null, resultSender);
-    function.execute(functionContext);
-    assertEquals("GOODv2", (String) resultSender.getResults());
-
-    // Test returning null for the Id
-    String functionNullIdString =
-        functionString.replace("return \"JarClassLoaderJUnitFunction\"", "return null");
-    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction",
-        functionNullIdString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    classLoader = new JarClassLoader(jarFile1, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-    assertNull(FunctionService.getFunction("JarClassLoaderJUnitFunction"));
-
-    // Test removing the JAR
-    classPathLoader = classPathLoader.remove(classLoader);
-    assertNull(FunctionService.getFunction("JarClassLoaderJUnitFunction"));
-  }
-
-  /**
-   * Ensure that abstract functions aren't added to the Function Service.
-   */
-  @Test
-  public void testAbstractFunction() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#1");
-
-    Properties properties = new Properties();
-    properties.setProperty(MCAST_PORT, "0");
-    CacheFactory cacheFactory = new CacheFactory(properties);
-    this.cache = (InternalCache) cacheFactory.create();
-
-    // Add an abstract Function to the Classpath
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("public abstract class JarClassLoaderJUnitFunction implements Function {");
-    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}}");
-    String functionString = stringBuffer.toString();
-
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader =
-        new JarClassLoader(jarFile1, "JarClassLoaderJUnitFunction.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    try {
-      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertNull(function);
-  }
-
-  @Test
-  public void testDeclarableFunctionsWithNoCacheXml() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnitNoXml.jar#1");
-
-    // Add a Declarable Function without parameters for the class to the Classpath
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("import java.util.Properties;");
-    stringBuffer.append("import org.apache.geode.cache.Declarable;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer
-        .append("public class JarClassLoaderJUnitFunctionNoXml implements Function, Declarable {");
-    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunctionNoXml\";}");
-    stringBuffer.append("public void init(Properties props) {}");
-    stringBuffer.append(
-        "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"NOPARMSv1\");}");
-    stringBuffer.append("public boolean hasResult() {return true;}");
-    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
-    stringBuffer.append("public boolean isHA() {return false;}}");
-    String functionString = stringBuffer.toString();
-
-    byte[] jarBytes = this.classBuilder
-        .createJarFromClassContent("JarClassLoaderJUnitFunctionNoXml", functionString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader =
-        new JarClassLoader(jarFile1, "JarClassLoaderJUnitFunctionNoXml.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    try {
-      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunctionNoXml");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    // Check to see if the function without parameters executes correctly
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunctionNoXml");
-    assertNotNull(function);
-    TestResultSender resultSender = new TestResultSender();
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("NOPARMSv1", (String) resultSender.getResults());
-  }
-
-  @Test
-  public void testDeclarableFunctionsWithoutParms() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#1");
-    final File jarFile2 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#2");
-
-    Properties properties = new Properties();
-    properties.setProperty(MCAST_PORT, "0");
-    CacheFactory cacheFactory = new CacheFactory(properties);
-    this.cache = (InternalCache) cacheFactory.create();
-
-    // Add a Declarable Function without parameters for the class to the Classpath
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("import java.util.Properties;");
-    stringBuffer.append("import org.apache.geode.cache.Declarable;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer
-        .append("public class JarClassLoaderJUnitFunction implements Function, Declarable {");
-    stringBuffer.append("public String getId() {return \"JarClassLoaderJUnitFunction\";}");
-    stringBuffer.append("public void init(Properties props) {}");
-    stringBuffer.append(
-        "public void execute(FunctionContext context) {context.getResultSender().lastResult(\"NOPARMSv1\");}");
-    stringBuffer.append("public boolean hasResult() {return true;}");
-    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
-    stringBuffer.append("public boolean isHA() {return false;}}");
-    String functionString = stringBuffer.toString();
-
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader =
-        new JarClassLoader(jarFile1, "JarClassLoaderJUnitFunction.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    try {
-      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    // Create a cache.xml file and configure the cache with it
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("<?xml version=\"1.0\"?>");
-    stringBuffer.append("<!DOCTYPE cache PUBLIC");
-    stringBuffer.append("  \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
-    stringBuffer.append("  \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
-    stringBuffer.append("<cache>");
-    stringBuffer.append("  <function-service>");
-    stringBuffer.append("    <function>");
-    stringBuffer.append("      <class-name>JarClassLoaderJUnitFunction</class-name>");
-    stringBuffer.append("    </function>");
-    stringBuffer.append(" </function-service>");
-    stringBuffer.append("</cache>");
-    String cacheXmlString = stringBuffer.toString();
-    this.cache.loadCacheXml(new ByteArrayInputStream(cacheXmlString.getBytes()));
-
-    // Check to see if the function without parameters executes correctly
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertNotNull(function);
-    TestResultSender resultSender = new TestResultSender();
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("NOPARMSv1", (String) resultSender.getResults());
-
-    // Update the second function (change the value returned from execute) by deploying a JAR file
-    functionString = functionString.replace("v1", "v2");
-    jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile2, jarBytes);
-
-    classLoader = new JarClassLoader(jarFile2, "JarClassLoaderJUnitFunction.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    // Check to see if the updated function without parameters executes correctly
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("NOPARMSv2", (String) resultSender.getResults());
-  }
-
-  @Test
-  public void testDeclarableFunctionsWithParms() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#1");
-    final File jarFile2 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#2");
-
-    Properties properties = new Properties();
-    properties.setProperty(MCAST_PORT, "0");
-    CacheFactory cacheFactory = new CacheFactory(properties);
-    this.cache = (InternalCache) cacheFactory.create();
-
-    // Add a Declarable Function with parameters to the class to the Classpath
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("import java.util.Properties;");
-    stringBuffer.append("import org.apache.geode.cache.Declarable;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer
-        .append("public class JarClassLoaderJUnitFunction implements Function, Declarable {");
-    stringBuffer.append("private Properties properties;");
-    stringBuffer.append(
-        "public String getId() {if(this.properties==null) {return \"JarClassLoaderJUnitFunction\";} else {return (String) this.properties.get(\"id\");}}");
-    stringBuffer.append("public void init(Properties props) {properties = props;}");
-    stringBuffer.append(
-        "public void execute(FunctionContext context) {context.getResultSender().lastResult(properties.get(\"returnValue\") + \"v1\");}");
-    stringBuffer.append("public boolean hasResult() {return true;}");
-    stringBuffer.append("public boolean optimizeForWrite() {return false;}");
-    stringBuffer.append("public boolean isHA() {return false;}}");
-    String functionString = stringBuffer.toString();
-
-    byte[] jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader =
-        new JarClassLoader(jarFile1, "JarClassLoaderJUnitFunction.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    try {
-      ClassPathLoader.getLatest().forName("JarClassLoaderJUnitFunction");
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath");
-    }
-
-    // Create a cache.xml file and configure the cache with it
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("<?xml version=\"1.0\"?>");
-    stringBuffer.append("<!DOCTYPE cache PUBLIC");
-    stringBuffer.append("  \"-//GemStone Systems, Inc.//GemFire Declarative Caching 7.0//EN\"");
-    stringBuffer.append("  \"http://www.gemstone.com/dtd/cache7_0.dtd\">");
-    stringBuffer.append("<cache>");
-    stringBuffer.append("  <function-service>");
-    stringBuffer.append("    <function>");
-    stringBuffer.append("      <class-name>JarClassLoaderJUnitFunction</class-name>");
-    stringBuffer.append(
-        "      <parameter name=\"id\"><string>JarClassLoaderJUnitFunctionA</string></parameter>");
-    stringBuffer.append("      <parameter name=\"returnValue\"><string>DOG</string></parameter>");
-    stringBuffer.append("    </function>");
-    stringBuffer.append("    <function>");
-    stringBuffer.append("      <class-name>JarClassLoaderJUnitFunction</class-name>");
-    stringBuffer.append(
-        "      <parameter name=\"id\"><string>JarClassLoaderJUnitFunctionB</string></parameter>");
-    stringBuffer.append("      <parameter name=\"returnValue\"><string>CAT</string></parameter>");
-    stringBuffer.append("    </function>");
-    stringBuffer.append(" </function-service>");
-    stringBuffer.append("</cache>");
-    String cacheXmlString = stringBuffer.toString();
-    this.cache.loadCacheXml(new ByteArrayInputStream(cacheXmlString.getBytes()));
-
-    // Check to see if the functions with parameters execute correctly
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunctionA");
-    assertNotNull(function);
-    TestResultSender resultSender = new TestResultSender();
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("DOGv1", (String) resultSender.getResults());
-
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionB");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("CATv1", (String) resultSender.getResults());
-
-    // Update the first function (change the value returned from execute)
-    functionString = functionString.replace("v1", "v2");
-    jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile2, jarBytes);
-    classLoader = new JarClassLoader(jarFile2, "JarClassLoaderJUnitFunction.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    // Check to see if the updated functions with parameters execute correctly
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionA");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("DOGv2", (String) resultSender.getResults());
-
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionB");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("CATv2", (String) resultSender.getResults());
-
-    // Update cache xml to add a new function and replace an existing one
-    cacheXmlString =
-        cacheXmlString.replace("JarClassLoaderJUnitFunctionA", "JarClassLoaderJUnitFunctionC")
-            .replace("CAT", "BIRD");
-    this.cache.loadCacheXml(new ByteArrayInputStream(cacheXmlString.getBytes()));
-
-    // Update the first function (change the value returned from execute)
-    functionString = functionString.replace("v2", "v3");
-    jarBytes =
-        this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitFunction", functionString);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    classLoader = new JarClassLoader(jarFile1, "JarClassLoaderJUnitFunction.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    // Check to see if the updated functions with parameters execute correctly
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionA");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("DOGv3", (String) resultSender.getResults());
-
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionC");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("DOGv3", (String) resultSender.getResults());
-
-    function = FunctionService.getFunction("JarClassLoaderJUnitFunctionB");
-    assertNotNull(function);
-    function.execute(new FunctionContextImpl(function.getId(), null, resultSender));
-    assertEquals("BIRDv3", (String) resultSender.getResults());
-  }
-
-  @Test
-  public void testDependencyBetweenJars() throws IOException, ClassNotFoundException {
-    final File parentJarFile = new File(JAR_PREFIX + "JarClassLoaderJUnitParent.jar#1");
-    final File usesJarFile = new File(JAR_PREFIX + "JarClassLoaderJUnitUses.jar#1");
-    final File functionJarFile = new File(JAR_PREFIX + "JarClassLoaderJUnitFunction.jar#1");
-
-    // Write out a JAR files.
-    StringBuffer stringBuffer = new StringBuffer();
-    stringBuffer.append("package jcljunit.parent;");
-    stringBuffer.append("public class JarClassLoaderJUnitParent {");
-    stringBuffer.append("public String getValueParent() {");
-    stringBuffer.append("return \"PARENT\";}}");
-
-    byte[] jarBytes = this.classBuilder.createJarFromClassContent(
-        "jcljunit/parent/JarClassLoaderJUnitParent", stringBuffer.toString());
-    writeJarBytesToFile(parentJarFile, jarBytes);
-    JarClassLoader parentClassLoader =
-        new JarClassLoader(parentJarFile, "JarClassLoaderJUnitParent.jar", jarBytes);
-
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("package jcljunit.uses;");
-    stringBuffer.append("public class JarClassLoaderJUnitUses {");
-    stringBuffer.append("public String getValueUses() {");
-    stringBuffer.append("return \"USES\";}}");
-
-    jarBytes = this.classBuilder.createJarFromClassContent("jcljunit/uses/JarClassLoaderJUnitUses",
-        stringBuffer.toString());
-    writeJarBytesToFile(usesJarFile, jarBytes);
-    JarClassLoader usesClassLoader =
-        new JarClassLoader(usesJarFile, "JarClassLoaderJUnitUses.jar", jarBytes);
-
-    stringBuffer = new StringBuffer();
-    stringBuffer.append("package jcljunit.function;");
-    stringBuffer.append("import jcljunit.parent.JarClassLoaderJUnitParent;");
-    stringBuffer.append("import jcljunit.uses.JarClassLoaderJUnitUses;");
-    stringBuffer.append("import org.apache.geode.cache.execute.Function;");
-    stringBuffer.append("import org.apache.geode.cache.execute.FunctionContext;");
-    stringBuffer.append(
-        "public class JarClassLoaderJUnitFunction  extends JarClassLoaderJUnitParent implements Function {");
-    stringBuffer.append("private JarClassLoaderJUnitUses uses = new JarClassLoaderJUnitUses();");
-    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 \"JarClassLoaderJUnitFunction\";}");
-    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(
-        "jcljunit/function/JarClassLoaderJUnitFunction", stringBuffer.toString());
-    writeJarBytesToFile(functionJarFile, jarBytes);
-    JarClassLoader functionClassLoader =
-        new JarClassLoader(functionJarFile, "JarClassLoaderJUnitFunction.jar", jarBytes);
-
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(functionClassLoader);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(parentClassLoader);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(usesClassLoader);
-
-    functionClassLoader.loadClassesAndRegisterFunctions();
-
-    Function function = FunctionService.getFunction("JarClassLoaderJUnitFunction");
-    assertNotNull(function);
-    TestResultSender resultSender = new TestResultSender();
-    FunctionContext functionContext = new FunctionContextImpl(function.getId(), null, resultSender);
-    function.execute(functionContext);
-    assertEquals("PARENT:USES", (String) resultSender.getResults());
-  }
-
-  @Test
-  public void testFindResource() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnitResource.jar#1");
-    ClassPathLoader classPathLoader = ClassPathLoader.createWithDefaults(false);
-    final String fileName = "file.txt";
-    final String fileContent = "FILE CONTENT";
-
-    byte[] jarBytes = this.classBuilder.createJarFromFileContent(fileName, fileContent);
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader =
-        new JarClassLoader(jarFile1, "JarClassLoaderJUnitResource.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    InputStream inputStream = classLoader.getResourceAsStream(fileName);
-    assertNotNull(inputStream);
-
-    final byte[] fileBytes = new byte[fileContent.length()];
-    inputStream.read(fileBytes);
-    inputStream.close();
-    assertTrue(fileContent.equals(new String(fileBytes)));
-  }
-
-  @Test
-  public void testUpdateClassInJar() throws IOException, ClassNotFoundException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#1");
-    final File jarFile2 = new File(JAR_PREFIX + "JarClassLoaderJUnit.jar#2");
-    ClassPathLoader classPathLoader = ClassPathLoader.createWithDefaults(false);
-
-    // First use of the JAR file
-    byte[] jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
-        "public class JarClassLoaderJUnitTestClass { public Integer getValue5() { return new Integer(5); } }");
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader = new JarClassLoader(jarFile1, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    try {
-      Class<?> clazz = classPathLoader.forName("JarClassLoaderJUnitTestClass");
-      Object object = clazz.newInstance();
-      Method getValue5Method = clazz.getMethod("getValue5", new Class[] {});
-      Integer value = (Integer) getValue5Method.invoke(object, new Object[] {});
-      assertEquals(value.intValue(), 5);
-
-    } catch (InvocationTargetException itex) {
-      fail("JAR file not correctly added to Classpath" + itex);
-    } catch (NoSuchMethodException nsmex) {
-      fail("JAR file not correctly added to Classpath" + nsmex);
-    } catch (InstantiationException iex) {
-      fail("JAR file not correctly added to Classpath" + iex);
-    } catch (IllegalAccessException iaex) {
-      fail("JAR file not correctly added to Classpath" + iaex);
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath" + cnfex);
-    }
-
-    // Now create an updated JAR file and make sure that the method from the new
-    // class is available.
-    jarBytes = this.classBuilder.createJarFromClassContent("JarClassLoaderJUnitTestClass",
-        "public class JarClassLoaderJUnitTestClass { public Integer getValue10() { return new Integer(10); } }");
-    writeJarBytesToFile(jarFile2, jarBytes);
-    classLoader = new JarClassLoader(jarFile2, "JarClassLoaderJUnit.jar", jarBytes);
-    classPathLoader = classPathLoader.addOrReplace(classLoader);
-    classLoader.loadClassesAndRegisterFunctions();
-
-    try {
-      Class<?> clazz = classPathLoader.forName("JarClassLoaderJUnitTestClass");
-      Object object = clazz.newInstance();
-      Method getValue10Method = clazz.getMethod("getValue10", new Class[] {});
-      Integer value = (Integer) getValue10Method.invoke(object, new Object[] {});
-      assertEquals(value.intValue(), 10);
-
-    } catch (InvocationTargetException itex) {
-      fail("JAR file not correctly added to Classpath" + itex);
-    } catch (NoSuchMethodException nsmex) {
-      fail("JAR file not correctly added to Classpath" + nsmex);
-    } catch (InstantiationException iex) {
-      fail("JAR file not correctly added to Classpath" + iex);
-    } catch (IllegalAccessException iaex) {
-      fail("JAR file not correctly added to Classpath" + iaex);
-    } catch (ClassNotFoundException cnfex) {
-      fail("JAR file not correctly added to Classpath" + cnfex);
-    }
-  }
-
-  @Test
-  public void testMultiThread() throws IOException {
-    final File jarFile1 = new File(JAR_PREFIX + "JarClassLoaderJUnitA.jar#1");
-    final File jarFile2 = new File(JAR_PREFIX + "JarClassLoaderJUnitB.jar#1");
-
-    // Add two JARs to the classpath
-    byte[] jarBytes = this.classBuilder.createJarFromName("JarClassLoaderJUnitA");
-    writeJarBytesToFile(jarFile1, jarBytes);
-    JarClassLoader classLoader = new JarClassLoader(jarFile1, "JarClassLoaderJUnitA.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-
-    jarBytes = this.classBuilder.createJarFromClassContent("com/jcljunit/JarClassLoaderJUnitB",
-        "package com.jcljunit; public class JarClassLoaderJUnitB {}");
-    writeJarBytesToFile(jarFile2, jarBytes);
-    classLoader = new JarClassLoader(jarFile2, "JarClassLoaderJUnitB.jar", jarBytes);
-    ClassPathLoader.getLatest().addOrReplaceAndSetLatest(classLoader);
-
-    String[] classNames = new String[] {"JarClassLoaderJUnitA", "com.jcljunit.JarClassLoaderJUnitB",
-        "NON-EXISTENT CLASS"};
-
-    // Spawn some threads which try to instantiate these classes
-    final int threadCount = 10;
-    final int numLoops = 1000;
-    final CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount + 1);
-    for (int i = 0; i < threadCount; i++) {
-      new ForNameExerciser(cyclicBarrier, numLoops, classNames).start();
-    }
-
-    // Wait for all of the threads to be ready
-    try {
-      cyclicBarrier.await();
-    } catch (InterruptedException iex) {
-      fail("Interrupted while waiting for barrier");
-    } catch (BrokenBarrierException bbex) {
-      fail("Broken barrier while waiting");
-    }
-
-    // Loop while each thread tries N times to instantiate a non-existent class
-    for (int i = 0; i < numLoops; i++) {
-      try {
-        cyclicBarrier.await(5, TimeUnit.SECONDS);
-      } catch (InterruptedException iex) {
-        fail("Interrupted while waiting for barrier");
-      } catch (TimeoutException tex) {
-        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
-        long[] threadIds = threadMXBean.findDeadlockedThreads();
-
-        if (threadIds != null) {
-          StringBuffer deadLockTrace = new StringBuffer();
-          for (long threadId : threadIds) {
-            ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId, 100);
-            deadLockTrace.append(threadInfo.getThreadName()).append("\n");
-            for (StackTraceElement stackTraceElem : threadInfo.getStackTrace()) {
-              deadLockTrace.append("\t").append(stackTraceElem).append("\n");
-            }
-          }
-
-          fail("Deadlock with trace:\n" + deadLockTrace.toString());
-        }
-
-        fail("Timeout while waiting for barrier - no deadlock detected");
-      } catch (BrokenBarrierException bbex) {
-        fail("Broken barrier while waiting");
-      }
-    }
-  }
-
-  private void deleteSavedJarFiles() {
-    File dirFile = new File(".");
-
-    // Find all created JAR files
-    File[] oldJarFiles = dirFile.listFiles(new FilenameFilter() {
-      @Override
-      public boolean accept(final File file, final String name) {
-        return JarClassLoaderJUnitTest.this.pattern.matcher(name).matches();
-      }
-    });
-
-    // Now delete them
-    if (oldJarFiles != null) {
-      for (File oldJarFile : oldJarFiles) {
-        if (!oldJarFile.delete()) {
-          RandomAccessFile randomAccessFile = null;
-          try {
-            randomAccessFile = new RandomAccessFile(oldJarFile, "rw");
-            randomAccessFile.setLength(0);
-          } catch (IOException ioex) {
-            fail("IOException when trying to deal with a stubborn JAR file");
-          } finally {
-            try {
-              if (randomAccessFile != null) {
-                randomAccessFile.close();
-              }
-            } catch (IOException ioex) {
-              fail("IOException when trying to deal with a stubborn JAR file");
-            }
-          }
-          oldJarFile.deleteOnExit();
-        }
-      }
-    }
-  }
-
-  private void writeJarBytesToFile(File jarFile, byte[] jarBytes) throws IOException {
-    final OutputStream outStream = new FileOutputStream(jarFile);
-    outStream.write(jarBytes);
-    outStream.close();
-  }
-
-  private static class TestResultSender implements ResultSender<Object> {
-    private Object result;
-
-    public TestResultSender() {}
-
-    protected Object getResults() {
-      return this.result;
-    }
-
-    @Override
-    public void lastResult(final Object lastResult) {
-      this.result = lastResult;
-    }
-
-    @Override
-    public void sendResult(final Object oneResult) {
-      throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void sendException(final Throwable t) {
-      throw new UnsupportedOperationException();
-    }
-  }
-
-  static final Random random = new Random();
-
-  private class ForNameExerciser extends Thread {
-    private final CyclicBarrier cyclicBarrier;
-    private final int numLoops;
-    private final String[] classNames;
-
-    ForNameExerciser(final CyclicBarrier cyclicBarrier, final int numLoops,
-        final String[] classNames) {
-      this.cyclicBarrier = cyclicBarrier;
-      this.numLoops = numLoops;
-      this.classNames = classNames;
-    }
-
-    @Override
-    public void run() {
-      try {
-        this.cyclicBarrier.await();
-      } catch (InterruptedException iex) {
-        fail("Interrupted while waiting for latch");
-      } catch (BrokenBarrierException bbex) {
-        fail("Broken barrier while waiting");
-      }
-      for (int i = 0; i < this.numLoops; i++) {
-        try {
-          // Random select a name from the list of class names and try to load it
-          String className = this.classNames[random.nextInt(this.classNames.length)];
-          ClassPathLoader.getLatest().forName(className);
-        } catch (ClassNotFoundException expected) { // expected
-        }
-        try {
-          this.cyclicBarrier.await();
-        } catch (InterruptedException iex) {
-          fail("Interrupted while waiting for barrrier");
-        } catch (BrokenBarrierException bbex) {
-          fail("Broken barrier while waiting");
-        }
-      }
-    }
-  }
-}


Mime
View raw message