This is an automated email from the ASF dual-hosted git repository.
jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 4a49226 GEODE-5459: Convert the classpath into a manifest jar for
ProcessWrapper (#2168)
4a49226 is described below
commit 4a4922691aefb21ae634ab7ba200a3533a074a40
Author: Jens Deppe <[email protected]>
AuthorDate: Fri Jul 20 10:37:43 2018 -0700
GEODE-5459: Convert the classpath into a manifest jar for ProcessWrapper
(#2168)
- This avoids too long command lines in Windows
---
...precatedCacheServerLauncherIntegrationTest.java | 22 ++++---
.../apache/geode/test/process/ProcessWrapper.java | 75 ++++++++++++++++++++--
2 files changed, 85 insertions(+), 12 deletions(-)
diff --git
a/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java
b/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java
index 447a097..5410eb7 100755
---
a/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java
+++
b/geode-core/src/integrationTest/java/org/apache/geode/internal/cache/DeprecatedCacheServerLauncherIntegrationTest.java
@@ -37,6 +37,7 @@ import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
+import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeoutException;
@@ -163,7 +164,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"-J-Xmx" + Runtime.getRuntime().maxMemory(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
"cache-xml-file=" + this.cacheXmlFileName, "-dir=" +
this.directoryPath,
- "-classpath=" + this.classpath);
+ "-classpath=" + getManifestJarFromClasspath());
execAndValidate("CacheServer pid: \\d+ status: running", "status",
"-dir=" + this.directoryPath);
@@ -181,7 +182,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"cache-xml-file=" + this.cacheXmlFile.getAbsolutePath(),
"log-file=" + this.logFile.getAbsolutePath(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "-server-port=" + this.serverPort,
- "-dir=" + this.directory.getAbsolutePath(), "-classpath=" +
this.classpath);
+ "-dir=" + this.directory.getAbsolutePath(), "-classpath=" +
getManifestJarFromClasspath());
execAndValidate("CacheServer pid: \\d+ status: running", "status",
"-dir=" + this.directory.getAbsolutePath());
@@ -204,7 +205,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"log-file=" + this.logFileName, "log-level=info",
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"",
"-server-port=" + this.serverPort, "-dir=" + this.directoryPath,
- "-classpath=" + this.classpath})
+ "-classpath=" + getManifestJarFromClasspath()})
.build();
this.processWrapper.execute();
@@ -261,7 +262,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"-J-Xmx" + Runtime.getRuntime().maxMemory(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
"cache-xml-file=" + this.cacheXmlFileName, "-dir=" +
this.directoryPath,
- "-classpath=" + this.classpath, "-rebalance");
+ "-classpath=" + getManifestJarFromClasspath(), "-rebalance");
await().atMost(2, MINUTES).until(() ->
assertThat(this.status.isStarted()).isTrue());
await().atMost(2, MINUTES).until(() ->
assertThat(this.status.isFinished()).isTrue());
@@ -286,7 +287,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"-J-Xmx" + Runtime.getRuntime().maxMemory(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
"cache-xml-file=" + this.cacheXmlFileName, "-dir=" +
this.directoryPath,
- "-classpath=" + this.classpath, "-rebalance");
+ "-classpath=" + getManifestJarFromClasspath(), "-rebalance");
await().atMost(2, MINUTES).until(() ->
assertThat(this.status.isStarted()).isTrue());
await().atMost(2, MINUTES).until(() ->
assertThat(this.status.isFinished()).isTrue());
@@ -306,7 +307,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"-J-Xmx" + Runtime.getRuntime().maxMemory(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
"cache-xml-file=" + this.cacheXmlFileName, "-dir=" +
this.directoryPath,
- "-classpath=" + this.classpath);
+ "-classpath=" + getManifestJarFromClasspath());
execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir="
+ this.directory);
@@ -336,7 +337,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"-J-Xmx" + Runtime.getRuntime().maxMemory(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
"cache-xml-file=" + this.cacheXmlFileName, "-dir=" +
this.directoryPath,
- "-classpath=" + this.classpath, "-server-port=" + this.commandPort);
+ "-classpath=" + getManifestJarFromClasspath(), "-server-port=" +
this.commandPort);
execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir="
+ this.directory);
@@ -368,7 +369,7 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
"-J-Xmx" + Runtime.getRuntime().maxMemory(),
"-J-Dgemfire.use-cluster-configuration=false",
"-J-Dgemfire.locators=\"\"", "log-file=" + this.logFileName,
"cache-xml-file=" + this.cacheXmlFileName, "-dir=" +
this.directoryPath,
- "-classpath=" + this.classpath, "-server-port=" + this.commandPort,
+ "-classpath=" + getManifestJarFromClasspath(), "-server-port=" +
this.commandPort,
"-server-bind-address=" + InetAddress.getLocalHost().getHostName());
execAndValidate("CacheServer pid: \\d+ status: running", "status", "-dir="
+ this.directory);
@@ -390,6 +391,11 @@ public class DeprecatedCacheServerLauncherIntegrationTest {
execAndValidate("The CacheServer has stopped\\.", "stop", "-dir=" +
this.directory);
}
+ private String getManifestJarFromClasspath() throws IOException {
+ List<String> parts =
Arrays.asList(this.classpath.split(File.pathSeparator));
+ return ProcessWrapper.createManifestJar(parts,
temporaryFolder.newFolder().getAbsolutePath());
+ }
+
private void unexportObject(final Remote object) {
if (object == null) {
return;
diff --git
a/geode-core/src/test/java/org/apache/geode/test/process/ProcessWrapper.java
b/geode-core/src/test/java/org/apache/geode/test/process/ProcessWrapper.java
index a02f298..6fcc9dd 100644
--- a/geode-core/src/test/java/org/apache/geode/test/process/ProcessWrapper.java
+++ b/geode-core/src/test/java/org/apache/geode/test/process/ProcessWrapper.java
@@ -18,7 +18,13 @@ import static
org.apache.geode.distributed.ConfigurationProperties.LOG_FILE;
import static org.junit.Assert.fail;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -26,11 +32,15 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.jar.Attributes;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
import java.util.regex.Pattern;
import org.apache.logging.log4j.Logger;
@@ -315,7 +325,8 @@ public class ProcessWrapper {
try {
synchronized (this.exitValue) {
final String[] command =
- defineCommand(jvmArgumentsList.toArray(new
String[jvmArgumentsList.size()]));
+ defineCommand(jvmArgumentsList.toArray(new
String[jvmArgumentsList.size()]),
+ workingDirectory.getCanonicalPath());
this.process = new
ProcessBuilder(command).directory(workingDirectory).start();
final StringBuilder processCommand = new StringBuilder();
@@ -364,14 +375,19 @@ public class ProcessWrapper {
}
}
- private String[] defineCommand(final String[] jvmArguments) {
+ private String[] defineCommand(final String[] jvmArguments, String
workingDir)
+ throws IOException {
final File javaBinDir = new File(System.getProperty("java.home"), "bin");
final File javaExe = new File(javaBinDir, "java");
- final List<String> argumentList = new ArrayList<String>();
+ String classPath = System.getProperty("java.class.path");
+ List<String> parts = Arrays.asList(classPath.split(File.pathSeparator));
+ String manifestJar = createManifestJar(parts, workingDir);
+
+ final List<String> argumentList = new ArrayList<>();
argumentList.add(javaExe.getPath());
argumentList.add("-classpath");
- argumentList.add(System.getProperty("java.class.path"));
+ argumentList.add(manifestJar);
// -d64 is not a valid option for windows and results in failure
final int bits = Integer.getInteger("sun.arch.data.model", 0).intValue();
@@ -439,6 +455,57 @@ public class ProcessWrapper {
return this.process;
}
+ /**
+ * Method to create a manifest jar from a list of jars or directories. The
provided entries are
+ * first converted to absolute paths and then converted to relative paths,
relative to the
+ * location provided. This is to support the Manifest's requirement that
class-paths only be
+ * relative. For example, if a jar is given as /a/b/c/foo.jar and the
location is /tmp/app, the
+ * following will happen:
+ * - the manifest jar will be created as /tmp/app/manifest.jar
+ * - the class-path attribute will be ../../a/b/c/foo.jar
+ *
+ * @return the path to the created manifest jar
+ */
+ public static String createManifestJar(List<String> entries, String
location) throws IOException {
+ // Must use the canonical path so that symbolic links are resolved
correctly
+ Path locationPath = new File(location).getCanonicalFile().toPath();
+ Files.createDirectories(locationPath);
+
+ List<String> manifestEntries = new ArrayList<>();
+ for (String jar : entries) {
+ Path absPath = Paths.get(jar).toAbsolutePath();
+ Path relPath = locationPath.relativize(absPath);
+ if (absPath.toFile().isDirectory()) {
+ manifestEntries.add(relPath.toString() + "/");
+ } else {
+ manifestEntries.add(relPath.toString());
+ }
+ }
+
+ Manifest manifest = new Manifest();
+ Attributes global = manifest.getMainAttributes();
+ global.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ global.put(new Attributes.Name("Class-Path"), String.join(" ",
manifestEntries));
+
+ // Generate a 'unique' 8 char name
+ String uuid = UUID.randomUUID().toString().substring(0, 8);
+ Path manifestJar = Paths.get(location, "manifest-" + uuid + ".jar");
+ JarOutputStream jos = null;
+ try {
+ File jarFile = manifestJar.toFile();
+ OutputStream os = new FileOutputStream(jarFile);
+ jos = new JarOutputStream(os, manifest);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (jos != null) {
+ jos.close();
+ }
+ }
+
+ return manifestJar.toString();
+ }
+
public static class Builder {
private String[] jvmArguments = null;
private Class<?> mainClass;