/*
* Capsule
* Copyright (c) 2014-2015, Parallel Universe Software Co. All rights reserved.
*
* This program and the accompanying materials are licensed under the terms
* of the Eclipse Public License v1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
import co.paralleluniverse.capsule.Jar;
import co.paralleluniverse.capsule.test.CapsuleTestUtils;
import co.paralleluniverse.capsule.test.CapsuleTestUtils.StringPrintStream;
import static co.paralleluniverse.capsule.test.CapsuleTestUtils.*;
import co.paralleluniverse.common.ZipFS;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import java.io.IOException;
import java.io.InputStream;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.nio.file.FileSystem;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarInputStream;
import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import org.junit.Before;
import static com.google.common.truth.Truth.*;
import java.nio.file.Paths;
import org.joor.Reflect;
//import static org.mockito.Mockito.*;
public class CapsuleTest {
/*
* As a general rule, we prefer system tests, and only create unit tests for particular methods that,
* while tested for integration, whose arguments don't get enough coverage in the system tests (like parsing methods and the like).
*
* All the tests in this test suite use an in-memory file system, and don't write to the disk at all.
*/
private final FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
private final Path cache = fs.getPath("/cache");
private final Path tmp = fs.getPath("/tmp");
private static final ClassLoader MY_CLASSLOADER = Capsule.class.getClassLoader();
private Properties props;
@Before
public void setUp() throws Exception {
props = new Properties(System.getProperties());
setProperties(props);
setCacheDir(cache);
resetOutputStreams();
TestCapsule.reset();
}
@After
public void tearDown() throws Exception {
fs.close();
}
//<editor-fold desc="System Tests">
/////////// System Tests ///////////////////////////////////
@Test
public void testSimpleExtract() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.addEntry("foo.jar", emptyInputStream())
.addEntry("a.class", emptyInputStream())
.addEntry("b.txt", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.class", emptyInputStream())
.addEntry("q/w/x.txt", emptyInputStream())
.addEntry("d\\f\\y.txt", emptyInputStream()) // test with Windows path
.addEntry("META-INF/x.txt", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
// dumpFileSystem(fs);
assertEquals(args, getAppArgs(pb));
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertEquals("com.acme.Foo", getProperty(pb, "capsule.app"));
assertEquals("com.acme.Foo", getEnv(pb, "CAPSULE_APP"));
assertEquals(appCache, path(getProperty(pb, "capsule.dir")));
assertEquals(absolutePath("capsule.jar"), path(getProperty(pb, "capsule.jar")));
assertEquals(appCache, path(getEnv(pb, "CAPSULE_DIR")));
assertEquals(absolutePath("capsule.jar"), path(getEnv(pb, "CAPSULE_JAR")));
assertEquals(list("com.acme.Foo", "hi", "there"), getMainAndArgs(pb));
assertTrue(Files.isDirectory(cache));
assertTrue(Files.isDirectory(cache.resolve("apps")));
assertTrue(Files.isDirectory(appCache));
assertTrue(Files.isRegularFile(appCache.resolve(".extracted")));
assertTrue(Files.isRegularFile(appCache.resolve("foo.jar")));
assertTrue(Files.isRegularFile(appCache.resolve("b.txt")));
assertTrue(Files.isDirectory(appCache.resolve("lib")));
assertTrue(Files.isRegularFile(appCache.resolve("lib").resolve("a.jar")));
assertTrue(!Files.isRegularFile(appCache.resolve("a.class")));
assertTrue(!Files.isRegularFile(appCache.resolve("lib").resolve("b.class")));
assertTrue(!Files.isDirectory(appCache.resolve("META-INF")));
assertTrue(!Files.isRegularFile(appCache.resolve("META-INF").resolve("x.txt")));
assertTrue(Files.isDirectory(appCache.resolve("q").resolve("w")));
assertTrue(Files.isDirectory(appCache.resolve("d").resolve("f")));
assertTrue(Files.isRegularFile(appCache.resolve("q").resolve("w").resolve("x.txt")));
assertTrue(Files.isRegularFile(appCache.resolve("d").resolve("f").resolve("y.txt")));
// assert_().that(getClassPath(pb)).has().item(absolutePath("capsule.jar"));
assert_().that(getClassPath(pb)).has().item(appCache.resolve("foo.jar"));
assert_().that(getClassPath(pb)).has().noneOf(appCache.resolve("lib").resolve("a.jar"));
}
@Test
public void testNoExtract() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.addEntry("foo.txt", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals(args, getAppArgs(pb));
assert_().that(getClassPath(pb)).has().item(absolutePath("capsule.jar"));
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertTrue(!Files.isDirectory(appCache));
}
@Test
public void testJDKClassPath() throws Exception {
assumeTrue(!isCI());
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
//.setAttribute("Extract-Capsule", "false")
.setAttribute("JDK-Required", "true")
.setListAttribute("App-Class-Path", list("$JAVA_HOME/lib/tools.jar", "lib/*"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path javaHome = path(capsule.getJavaHome().toString()); // different FS
assertEquals(args, getAppArgs(pb));
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
final String h = javaHome.toString();
assert_().that(!h.contains("jre") && (h.contains("jdk") || Files.exists(javaHome.resolve("include").resolve("jni.h"))));
assert_().that(h).doesNotContain("jre");
assert_().that(getClassPath(pb)).has().allOf(
javaHome.resolve("lib/tools.jar"),
appCache.resolve("foo.jar"),
appCache.resolve("lib").resolve("a.jar"),
appCache.resolve("lib").resolve("b.jar"));
}
@Test
public void testLogLevel() throws Exception {
setSTDERR(DEVNULL);
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Extract-Capsule", "false")
.setAttribute("Capsule-Log-Level", "verbose");
newCapsule(jar);
assertTrue(Capsule.isLogging(2));
assertTrue(!Capsule.isLogging(3));
props.setProperty("capsule.log", "none");
newCapsule(jar);
assertTrue(Capsule.isLogging(0));
assertTrue(!Capsule.isLogging(1));
props.setProperty("capsule.log", "quiet");
newCapsule(jar);
assertTrue(Capsule.isLogging(1));
assertTrue(!Capsule.isLogging(2));
props.setProperty("capsule.log", "");
newCapsule(jar);
assertTrue(Capsule.isLogging(1));
assertTrue(!Capsule.isLogging(2));
props.setProperty("capsule.log", "verbose");
newCapsule(jar);
assertTrue(Capsule.isLogging(2));
assertTrue(!Capsule.isLogging(3));
props.setProperty("capsule.log", "debug");
newCapsule(jar);
assertTrue(Capsule.isLogging(3));
}
@Test
public void testCapsuleJavaHome() throws Exception {
props.setProperty("capsule.java.home", "/my/1.7.0.jdk/home");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Extract-Capsule", "false")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("/my/1.7.0.jdk/home/bin/java" + (Capsule.isWindows() ? ".exe" : ""), pb.command().get(0));
}
@Test
public void testCapsuleJavaCmd() throws Exception {
props.setProperty("capsule.java.cmd", "/my/java/home/gogo");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Extract-Capsule", "false")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("/my/java/home/gogo", pb.command().get(0));
}
@Test
public void testClassPath() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("App-Class-Path", list("lib/a.jar", "lib/b.jar", "lib2/*.jar"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream())
.addEntry("lib2/c.jar", emptyInputStream())
.addEntry("lib2/d.jar", emptyInputStream())
.addEntry("lib2/e.txt", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertTrue(Files.isDirectory(appCache.resolve("lib")));
assertTrue(Files.isRegularFile(appCache.resolve("lib").resolve("a.jar")));
assertTrue(Files.isRegularFile(appCache.resolve("lib2").resolve("c.jar")));
assertTrue(Files.isRegularFile(appCache.resolve("lib2").resolve("d.jar")));
assertTrue(Files.isRegularFile(appCache.resolve("lib2").resolve("e.txt")));
// assert_().that(getClassPath(pb)).has().item(absolutePath("capsule.jar"));
assert_().that(getClassPath(pb)).has().item(appCache.resolve("foo.jar"));
assert_().that(getClassPath(pb)).has().item(appCache.resolve("lib").resolve("a.jar"));
assert_().that(getClassPath(pb)).has().item(appCache.resolve("lib").resolve("b.jar"));
assert_().that(getClassPath(pb)).has().item(appCache.resolve("lib2").resolve("c.jar"));
assert_().that(getClassPath(pb)).has().item(appCache.resolve("lib2").resolve("d.jar"));
assert_().that(getClassPath(pb)).has().noneOf(appCache.resolve("lib2").resolve("e.txt"));
}
@Test
public void testNatives1() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Library-Path-A", list("lib/a.so"))
.setListAttribute("Library-Path-P", list("lib/b.so"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.so", emptyInputStream())
.addEntry("lib/b.so", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream())
.addEntry("lib/d.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
int len = paths(getProperty(pb, "java.library.path")).size();
assert_().that(paths(getProperty(pb, "java.library.path")).get(0)).isEqualTo(appCache.resolve("lib").resolve("b.so"));
assert_().that(paths(getProperty(pb, "java.library.path")).get(len - 2)).isEqualTo(appCache.resolve("lib").resolve("a.so"));
assert_().that(paths(getProperty(pb, "java.library.path")).get(len - 1)).isEqualTo(appCache);
}
@Test
public void testNatives2() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Library-Path-A", list("lib/a.so"))
.setListAttribute("Library-Path-P", list("lib/b.so"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.so", emptyInputStream())
.addEntry("lib/b.so", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream())
.addEntry("lib/d.jar", emptyInputStream());
props.setProperty("java.library.path", "/foo/bar");
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(paths(getProperty(pb, "java.library.path"))).isEqualTo(list(
appCache.resolve("lib").resolve("b.so"),
path("/foo", "bar"),
appCache.resolve("lib").resolve("a.so"),
appCache));
}
@Test
public void testNativesWithDeps() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Linux", "Native-Dependencies", list("com.acme:baz-linux:3.4=libbaz.so"))
.setListAttribute("Windows", "Native-Dependencies", list("com.acme:baz-win:3.4=libbaz.dll"))
.setListAttribute("MacOS", "Native-Dependencies", list("com.acme:baz-macos:3.4=libbaz.dylib"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.so", emptyInputStream())
.addEntry("lib/b.so", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream())
.addEntry("lib/d.jar", emptyInputStream());
Path bazLinuxPath = mockDep("com.acme:baz-linux:3.4", "so");
Path bazWindowsPath = mockDep("com.acme:baz-win:3.4", "dll");
Path bazMacPath = mockDep("com.acme:baz-macos:3.4", "dylib");
Files.createDirectories(bazLinuxPath.getParent());
Files.createFile(bazLinuxPath);
Files.createFile(bazWindowsPath);
Files.createFile(bazMacPath);
props.setProperty("java.library.path", "/foo/bar");
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(paths(getProperty(pb, "java.library.path"))).has().item(appCache);
if (Capsule.isUnix())
assertTrue(Files.isRegularFile(appCache.resolve("libbaz.so")));
else if (Capsule.isWindows())
assertTrue(Files.isRegularFile(appCache.resolve("libbaz.dll")));
else if (Capsule.isMac())
assertTrue(Files.isRegularFile(appCache.resolve("libbaz.dylib")));
}
@Test
public void testBootClassPath1() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Boot-Class-Path-A", list("lib/a.jar"))
.setListAttribute("Boot-Class-Path-P", list("lib/b.jar"))
.setListAttribute("Boot-Class-Path", list("lib/c.jar", "lib/d.jar"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream())
.addEntry("lib/d.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().item(appCache.resolve("lib").resolve("c.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().item(appCache.resolve("lib").resolve("d.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath/a"))).isEqualTo(list(appCache.resolve("lib").resolve("a.jar")));
assert_().that(paths(getOption(pb, "-Xbootclasspath/p"))).isEqualTo(list(appCache.resolve("lib").resolve("b.jar")));
}
@Test
public void testBootClassPath2() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Boot-Class-Path-A", list("lib/a.jar"))
.setListAttribute("Boot-Class-Path-P", list("lib/b.jar"))
.setListAttribute("Boot-Class-Path", list("lib/c.jar", "lib/d.jar"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream())
.addEntry("lib/d.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Xbootclasspath:/foo/bar");
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(getOption(pb, "-Xbootclasspath")).isEqualTo("/foo/bar");
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().noneOf(appCache.resolve("lib").resolve("c.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().noneOf(appCache.resolve("lib").resolve("d.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath/a"))).isEqualTo(list(appCache.resolve("lib").resolve("a.jar")));
assert_().that(paths(getOption(pb, "-Xbootclasspath/p"))).isEqualTo(list(appCache.resolve("lib").resolve("b.jar")));
}
@Test
public void testBootClassPathWithDeps() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Boot-Class-Path-A", list("com.acme:baz:3.4"))
.setListAttribute("Boot-Class-Path-P", list("lib/b.jar"))
.setListAttribute("Boot-Class-Path", list("lib/c.jar", "com.acme:bar:1.2"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream());
List<Path> barPath = mockDep("com.acme:bar:1.2", "jar", "com.acme:bar:1.2");
List<Path> bazPath = mockDep("com.acme:baz:3.4", "jar", "com.acme:baz:3.4");
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().item(appCache.resolve("lib").resolve("c.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().allFrom(barPath);
assert_().that(paths(getOption(pb, "-Xbootclasspath/a"))).has().allFrom(bazPath);
assert_().that(paths(getOption(pb, "-Xbootclasspath/p"))).isEqualTo(list(appCache.resolve("lib").resolve("b.jar")));
}
@Test
public void testBootClassPathWithEmbeddedDeps() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Boot-Class-Path-P", list("lib/b.jar"))
.setListAttribute("Boot-Class-Path", list("lib/c.jar", "com.acme:bar:1.2"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream())
.addEntry("lib/c.jar", emptyInputStream())
.addEntry("bar-1.2.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().item(appCache.resolve("lib").resolve("c.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().item(appCache.resolve("bar-1.2.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath/p"))).isEqualTo(list(appCache.resolve("lib").resolve("b.jar")));
}
@Test
public void testDependencies1() throws Exception {
List<String> deps = list("com.acme:bar:1.2", "com.acme:baz:3.4:jdk8");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Dependencies", deps)
.setListAttribute("App-Class-Path", list("com.acme:wat:5.8", "com.acme:woo"))
.addEntry("foo.jar", emptyInputStream());
final List<Path> paths = new ArrayList<>();
paths.add(mockDep("com.acme:bar:1.2", "jar"));
paths.addAll(mockDep("com.acme:baz:3.4:jdk8", "jar", "com.google:guava:18.0"));
paths.add(mockDep("com.acme:wat:5.8", "jar"));
paths.addAll(mockDep("com.acme:woo", "jar", "org.apache:tomcat:8.0", "io.jetty:jetty:123.0"));
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assert_().that(getClassPath(pb)).has().allFrom(paths);
}
public void whenDepManagerThenDontResolveEmbeddedDeps() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("Boot-Class-Path", list("lib/c.jar", "com.acme:bar:1.2"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("bar-1.2.jar", emptyInputStream());
Path barPath = mockDep("com.acme:bar:1.2", "jar");
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
List<String> args = list("hi", "there");
List<String> cmdLine = list();
ProcessBuilder pb = newCapsule(jar).prepareForLaunch(cmdLine, args);
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().noneOf(appCache.resolve("bar-1.2.jar"));
assert_().that(paths(getOption(pb, "-Xbootclasspath"))).has().item(barPath);
}
@Test
public void testCapsuleInClassPath() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setListAttribute("App-Class-Path", list("lib/a.jar", "lib/b.jar"))
.setAttribute("Capsule-In-Class-Path", "false")
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertTrue(Files.isDirectory(appCache.resolve("lib")));
assertTrue(Files.isRegularFile(appCache.resolve("lib").resolve("a.jar")));
assert_().that(getClassPath(pb)).has().noneOf(absolutePath("capsule.jar"));
assert_().that(getClassPath(pb)).has().allOf(
appCache.resolve("foo.jar"),
appCache.resolve("lib").resolve("a.jar"),
appCache.resolve("lib").resolve("b.jar"));
}
@Test
public void testSystemProperties() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz");
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("x", getProperty(pb, "foo"));
assertEquals("", getProperty(pb, "bar"));
assertEquals("", getProperty(pb, "zzz"));
assertEquals("33", getProperty(pb, "baz"));
}
@Test
public void testPlatformSepcific() throws Exception {
props.setProperty("capsule.java.home", "/my/1.8.0.jdk/home");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Linux", "System-Properties", "bar baz=33 foo=y os=lin")
.setAttribute("MacOS", "System-Properties", "bar baz=33 foo=y os=mac")
.setAttribute("Windows", "System-Properties", "bar baz=33 foo=y os=win")
.setAttribute("Java-8", "System-Properties", "jjj=8")
.setAttribute("Java-7", "System-Properties", "jjj=7")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz");
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("x", getProperty(pb, "foo"));
assertEquals("", getProperty(pb, "bar"));
assertEquals("", getProperty(pb, "zzz"));
assertEquals("33", getProperty(pb, "baz"));
assertEquals("8", getProperty(pb, "jjj"));
if (Capsule.isWindows())
assertEquals("win", getProperty(pb, "os"));
else if (Capsule.isUnix())
assertEquals("lin", getProperty(pb, "os"));
if (Capsule.isMac())
assertEquals("mac", getProperty(pb, "os"));
}
@Test
public void testJVMArgs() throws Exception {
props.setProperty("capsule.jvm.args", "-Xfoo500 -Xbar:120");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("JVM-Args", "-Xmx100 -Xms10 -Xfoo400")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Xms15");
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertTrue(getJvmArgs(pb).contains("-Xmx100"));
assertTrue(getJvmArgs(pb).contains("-Xms15"));
assertTrue(!getJvmArgs(pb).contains("-Xms10"));
assertTrue(getJvmArgs(pb).contains("-Xfoo500"));
assertTrue(getJvmArgs(pb).contains("-Xbar:120"));
}
@Test
public void testAgents() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Java-Agents", "ja1.jar ja2.jar=a=1,b=2 com.acme:bar=x=hi")
.setAttribute("Native-Agents", "na1=c=3,d=4 na2")
.addEntry("foo.jar", emptyInputStream());
Path barPath = mockDep("com.acme:bar", "jar", "com.acme:bar:1.2").get(0);
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(getJvmArgs(pb)).has().allOf("-javaagent:" + appCache.resolve("ja1.jar"));
assert_().that(getJvmArgs(pb)).has().item("-javaagent:" + appCache.resolve("ja2.jar") + "=a=1,b=2");
assert_().that(getJvmArgs(pb)).has().item("-javaagent:" + barPath + "=x=hi");
assert_().that(getJvmArgs(pb)).has().item("-agentpath:" + appCache.resolve("na1." + Capsule.getNativeLibExtension()) + "=c=3,d=4");
assert_().that(getJvmArgs(pb)).has().item("-agentpath:" + appCache.resolve("na2." + Capsule.getNativeLibExtension()));
}
@Test
public void testMode() throws Exception {
props.setProperty("capsule.mode", "ModeX");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.setAttribute("ModeX", "System-Properties", "bar baz=55 foo=w")
.setAttribute("ModeX", "Description", "This is a secret mode")
.setAttribute("ModeX-Linux", "System-Properties", "bar baz=55 foo=w os=lin")
.setAttribute("ModeX-MacOS", "System-Properties", "bar baz=55 foo=w os=mac")
.setAttribute("ModeX-Windows", "System-Properties", "bar baz=55 foo=w os=win")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz");
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("x", getProperty(pb, "foo"));
assertEquals("", getProperty(pb, "bar"));
assertEquals("", getProperty(pb, "zzz"));
assertEquals("55", getProperty(pb, "baz"));
assertEquals(new HashSet<String>(list("ModeX")), capsule.getModes());
assertEquals("This is a secret mode", capsule.getModeDescription("ModeX"));
if (Capsule.isWindows())
assertEquals("win", getProperty(pb, "os"));
else if (Capsule.isUnix())
assertEquals("lin", getProperty(pb, "os"));
if (Capsule.isMac())
assertEquals("mac", getProperty(pb, "os"));
}
@Test(expected = Exception.class)
public void testMode2() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.setAttribute("ModeX", "Application-Class", "com.acme.Bar")
.addEntry("foo.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
newCapsule(jar).prepareForLaunch(cmdLine, args);
}
@Test
public void testApplicationArtifact() throws Exception {
Jar bar = new Jar()
.setAttribute("Main-Class", "com.acme.Bar")
.addEntry("com/acme/Bar.class", emptyInputStream());
Path barPath = mockDep("com.acme:bar:1.2", "jar");
Files.createDirectories(barPath.getParent());
bar.write(barPath);
Jar jar = newCapsuleJar()
.setAttribute("Application", "com.acme:bar:1.2");
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assert_().that(getClassPath(pb)).has().item(barPath);
assertEquals("com.acme.Bar", getMainClass(pb));
}
@Test
public void testEmbeddedArtifact() throws Exception {
Jar bar = new Jar()
.setAttribute("Main-Class", "com.acme.Bar")
.setAttribute("Class-Path", "lib/liba.jar lib/libb.jar")
.addEntry("com/acme/Bar.class", emptyInputStream());
Jar jar = newCapsuleJar()
.setAttribute("Application", "bar.jar")
.setAttribute("Application-Name", "AcmeFoo")
.setAttribute("Application-Version", "1.0")
.addEntry("bar.jar", bar.toByteArray())
.addEntry("lib/liba.jar", emptyInputStream())
.addEntry("lib/libb.jar", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("AcmeFoo_1.0");
assert_().that(getClassPath(pb)).has().item(appCache.resolve("bar.jar"));
// assert_().that(getClassPath(pb)).has().item(appCache.resolve("lib").resolve("liba.jar"));
// assert_().that(getClassPath(pb)).has().item(appCache.resolve("lib").resolve("libb.jar"));
assertEquals("com.acme.Bar", getMainClass(pb));
}
@Test
public void testScript() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Dependencies", "com.acme:bar:1.2")
.setAttribute("Linux", "Application-Script", "scr.sh")
.setAttribute("MacOS", "Application-Script", "scr.sh")
.setAttribute("Windows", "Application-Script", "scr.bat")
.addEntry("scr.sh", emptyInputStream())
.addEntry("scr.bat", emptyInputStream())
.addEntry("foo.jar", emptyInputStream());
Path barPath = mockDep("com.acme:bar:1.2", "jar");
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(jar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertEquals(list(appCache.resolve(Capsule.isWindows() ? "scr.bat" : "scr.sh").toString(), "hi", "there"),
pb.command());
assert_().that(getEnv(pb, "CLASSPATH")).contains(appCache.resolve("foo.jar") + PS + barPath);
}
@Test
public void testReallyExecutableCapsule() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Main-Class", "MyCapsule")
.setAttribute("Premain-Class", "MyCapsule")
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.setAttribute("JVM-Args", "-Xmx100 -Xms10")
.setReallyExecutable(true)
.addEntry("a.class", emptyInputStream());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz", "-Xms15");
Path capsuleJar = absolutePath("capsule.jar");
jar.write(capsuleJar);
Capsule.newCapsule(MY_CLASSLOADER, capsuleJar).prepareForLaunch(cmdLine, args);
}
@Test
public void testSimpleCaplet1() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Main-Class", "MyCapsule")
.setAttribute("Premain-Class", "MyCapsule")
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.setAttribute("JVM-Args", "-Xmx100 -Xms10")
.addClass(MyCapsule.class);
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz", "-Xms15");
Path capsuleJar = absolutePath("capsule.jar");
jar.write(capsuleJar);
Capsule capsule = Capsule.newCapsule(MY_CLASSLOADER, capsuleJar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("x", getProperty(pb, "foo"));
assertEquals("", getProperty(pb, "bar"));
assertEquals("", getProperty(pb, "zzz"));
assertEquals("44", getProperty(pb, "baz"));
assertTrue(getJvmArgs(pb).contains("-Xmx3000"));
assertTrue(!getJvmArgs(pb).contains("-Xmx100"));
assertTrue(getJvmArgs(pb).contains("-Xms15"));
assertTrue(!getJvmArgs(pb).contains("-Xms10"));
}
@Test
public void testSimpleCaplet2() throws Exception {
Jar jar = newCapsuleJar()
.setListAttribute("Caplets", list("MyCapsule"))
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.setAttribute("JVM-Args", "-Xmx100 -Xms10")
.setListAttribute("App-Class-Path", list("lib/*"))
.addEntry("foo.jar", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.jar", emptyInputStream())
.addClass(MyCapsule.class);
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz", "-Xms15");
Path capsuleJar = absolutePath("capsule.jar");
jar.write(capsuleJar);
Capsule capsule = Capsule.newCapsule(MY_CLASSLOADER, capsuleJar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assert_().that(getProperty(pb, "foo")).isEqualTo("x");
assert_().that(getProperty(pb, "bar")).isEqualTo("");
assert_().that(getProperty(pb, "zzz")).isEqualTo("");
assert_().that(getProperty(pb, "baz")).isEqualTo("44");
assert_().that(getJvmArgs(pb)).has().item("-Xmx3000");
assert_().that(getJvmArgs(pb)).has().noneOf("-Xmx100");
assert_().that(getJvmArgs(pb)).has().item("-Xms15");
assert_().that(getJvmArgs(pb)).has().noneOf("-Xms10");
assert_().that(getClassPath(pb)).has().allOf(
fs.getPath("/foo/bar"),
appCache.resolve("foo.jar"),
appCache.resolve("lib").resolve("a.jar"),
appCache.resolve("lib").resolve("b.jar"));
}
@Test
public void testEmbeddedCaplet() throws Exception {
Jar bar = newCapsuleJar()
.setListAttribute("Caplets", list("MyCapsule"))
.addClass(MyCapsule.class);
Jar jar = newCapsuleJar()
.setListAttribute("Caplets", list("com.acme:mycapsule:0.9"))
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "bar baz=33 foo=y")
.setAttribute("JVM-Args", "-Xmx100 -Xms10")
.addEntry("mycapsule-0.9.jar", bar.toByteArray());
List<String> args = list("hi", "there");
List<String> cmdLine = list("-Dfoo=x", "-Dzzz", "-Xms15");
Path capsuleJar = absolutePath("capsule.jar");
jar.write(capsuleJar);
Capsule capsule = Capsule.newCapsule(MY_CLASSLOADER, capsuleJar);
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertEquals("x", getProperty(pb, "foo"));
assertEquals("", getProperty(pb, "bar"));
assertEquals("", getProperty(pb, "zzz"));
assertEquals("44", getProperty(pb, "baz"));
assertTrue(getJvmArgs(pb).contains("-Xmx3000"));
assertTrue(!getJvmArgs(pb).contains("-Xmx100"));
assertTrue(getJvmArgs(pb).contains("-Xms15"));
assertTrue(!getJvmArgs(pb).contains("-Xms10"));
}
@Test
public void testWrapperCapsule() throws Exception {
Jar wrapper = newCapsuleJar()
.setAttribute("Caplets", "MyCapsule")
.setAttribute("System-Properties", "p1=555")
.addClass(Capsule.class)
.addClass(MyCapsule.class);
Jar app = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "p1=111")
.setListAttribute("App-Class-Path", list("lib/a.jar"))
.addClass(Capsule.class)
.addEntry("foo.jar", emptyInputStream())
.addEntry("a.class", emptyInputStream())
.addEntry("b.txt", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.class", emptyInputStream())
.addEntry("META-INF/x.txt", emptyInputStream());
Path fooPath = mockDep("com.acme:foo", "jar", "com.acme:foo:1.0").get(0);
Files.createDirectories(fooPath.getParent());
app.write(fooPath);
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(wrapper).setTarget("com.acme:foo");
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assertTrue(capsule.hasCaplet("MyCapsule"));
assertTrue(capsule.toString() != null); // exercise toString
// dumpFileSystem(fs);
assertTrue(pb != null);
String appId = capsule.getAppId();
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertEquals("com.acme.Foo", getProperty(pb, "capsule.app"));
assertEquals(appCache.toString(), getProperty(pb, "capsule.dir"));
assertEquals(list("com.acme.Foo", "hi", "there"), getMainAndArgs(pb));
assertTrue(Files.isDirectory(cache));
assertTrue(Files.isDirectory(cache.resolve("apps")));
assertTrue(Files.isDirectory(appCache));
assertTrue(Files.isRegularFile(appCache.resolve(".extracted")));
assertTrue(Files.isRegularFile(appCache.resolve("foo.jar")));
assertTrue(Files.isRegularFile(appCache.resolve("b.txt")));
assertTrue(Files.isDirectory(appCache.resolve("lib")));
assertTrue(Files.isRegularFile(appCache.resolve("lib").resolve("a.jar")));
assertTrue(!Files.isRegularFile(appCache.resolve("a.class")));
assertTrue(!Files.isRegularFile(appCache.resolve("lib").resolve("b.class")));
assertTrue(!Files.isDirectory(appCache.resolve("META-INF")));
assertTrue(!Files.isRegularFile(appCache.resolve("META-INF").resolve("x.txt")));
assert_().that(getClassPath(pb)).has().allOf(
appCache.resolve("foo.jar"),
appCache.resolve("lib").resolve("a.jar"));
assertEquals("111", getProperty(pb, "p1"));
}
@Test
public void testWrapperCapsuleNonCapsuleApp() throws Exception {
Jar wrapper = newCapsuleJar()
.setAttribute("Main-Class", "MyCapsule")
.setAttribute("Premain-Class", "MyCapsule")
.setAttribute("System-Properties", "p1=555")
.addClass(Capsule.class)
.addClass(MyCapsule.class);
Jar app = new Jar()
.setAttribute("Main-Class", "com.acme.Foo")
.setAttribute("System-Properties", "p1=111")
.setAttribute("Class-Path", "lib/a.jar lib/b.jar")
.addEntry("a.class", emptyInputStream())
.addEntry("b.txt", emptyInputStream())
.addEntry("META-INF/x.txt", emptyInputStream());
Path fooPath = path("foo-1.0.jar");
app.write(fooPath);
List<String> args = list("hi", "there");
List<String> cmdLine = list();
Capsule capsule = newCapsule(wrapper).setTarget(fooPath.toString());
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
// dumpFileSystem(fs);
assertTrue(pb != null);
String appId = capsule.getAppId();
Path appCache = cache.resolve("apps").resolve("com.acme.Foo");
assertEquals(list("com.acme.Foo", "hi", "there"), getMainAndArgs(pb));
//assertTrue(!Files.exists(appCache));
assertTrue(!Files.exists(appCache.resolve("b.txt")));
assertTrue(!Files.exists(appCache.resolve("a.class")));
assert_().that(getClassPath(pb)).has().item(fooPath.toAbsolutePath());
// assert_().that(getClassPath(pb)).has().allOf(
// path("lib").resolve("a.jar").toAbsolutePath(),
// path("lib").resolve("b.jar").toAbsolutePath());
assert_().that(getClassPath(pb)).has().noneOf(
absolutePath("capsule.jar"),
appCache.resolve("lib").resolve("a.jar"),
appCache.resolve("lib").resolve("b.jar"));
assertEquals("555", getProperty(pb, "p1"));
}
@Test
public void testCapsuleJvmArgsParsing() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Main-Class", "MyCapsule")
.setAttribute("Premain-Class", "MyCapsule")
.setAttribute("Application-Class", "com.acme.Foo")
.addClass(MyCapsule.class);
Path capsuleJar = absolutePath("capsule.jar");
jar.write(capsuleJar);
Capsule capsule = Capsule.newCapsule(MY_CLASSLOADER, capsuleJar);
List<String> args = list();
List<String> cmdLine = list();
Capsule.setProperty("capsule.jvm.args",
"-Ddouble.quoted.arg=\"escape me\" "
+ "-Dsingle.quoted.arg='escape me'");
ProcessBuilder pb = capsule.prepareForLaunch(cmdLine, args);
assert_().that(getProperty(pb, "double.quoted.arg")).isEqualTo("escape me");
assert_().that(getProperty(pb, "single.quoted.arg")).isEqualTo("escape me");
}
@Test(expected = IllegalArgumentException.class)
public void testWrapperCapsuleNoMain() throws Exception {
Jar wrapper = newCapsuleJar()
.setAttribute("Main-Class", "MyCapsule")
.setAttribute("Premain-Class", "MyCapsule")
.setAttribute("System-Properties", "p1=555")
.addClass(Capsule.class)
.addClass(MyCapsule.class);
Jar app = new Jar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "p1=111")
.setListAttribute("App-Class-Path", list("lib/a.jar"))
.addClass(Capsule.class)
.addEntry("foo.jar", emptyInputStream());
Path fooPath = path("foo-1.0.jar");
app.write(fooPath);
newCapsule(wrapper).setTarget(fooPath.toString());
}
@Test
public void testProcessCommandLineOptions() throws Exception {
List<String> args = new ArrayList<>(list("-java-home", "/foo/bar", "-reset", "-jvm-args=a b c", "-java-cmd", "gogo", "hi", "there"));
List<String> jvmArgs = list("-Dcapsule.java.cmd=wow");
processCmdLineOptions(args, jvmArgs);
assertEquals("/foo/bar", props.getProperty("capsule.java.home"));
assertEquals("true", props.getProperty("capsule.reset"));
assertEquals("a b c", props.getProperty("capsule.jvm.args"));
assertEquals(null, props.getProperty("capsule.java.cmd")); // overriden
assertEquals(list("hi", "there"), args);
}
private static void processCmdLineOptions(List<String> args, List<String> jvmArgs) {
Reflect.on(Capsule.class).call("processCmdLineOptions", args, jvmArgs);
}
@Test
public void testTrampoline() throws Exception {
props.setProperty("capsule.java.home", "/my/1.7.0.jdk/home");
props.setProperty("capsule.trampoline", "true");
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Extract-Capsule", "false")
.addEntry("foo.jar", emptyInputStream());
Class<?> capsuleClass = loadCapsule(jar);
setProperties(capsuleClass, props);
StringPrintStream out = setSTDOUT(capsuleClass, new StringPrintStream());
int exit = main0(capsuleClass, "hi", "there!");
assertEquals(0, exit);
String res = out.toString();
assert_().that(res).matches("[^\n]+\n\\z"); // a single line, teminated with a newline
assert_().that(res).startsWith("\"" + "/my/1.7.0.jdk/home/bin/java" + (Capsule.isWindows() ? ".exe" : "") + "\"");
assert_().that(res).endsWith("\"com.acme.Foo\" \"hi\" \"there!\"\n");
}
private static int main0(Class<?> clazz, String... args) {
return Reflect.on(clazz).call("main0", (Object) args).get();
}
private static boolean runActions(Object capsule, List<String> args) {
return Reflect.on(capsule.getClass()).call("runActions", capsule, args).get();
}
@Test
public void testPrintHelp() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Application-Version", "12.34")
.addEntry("foo.jar", emptyInputStream());
props.setProperty("capsule.help", "");
Class<?> capsuleClass = loadCapsule(jar);
setProperties(capsuleClass, props);
StringPrintStream out = setSTDERR(capsuleClass, new StringPrintStream());
Object capsule = newCapsule(capsuleClass);
boolean found = runActions(capsule, null);
String res = out.toString();
assert_().that(found).isTrue();
assert_().that(res).contains("USAGE: ");
}
@Test
public void testPrintCapsuleVersion() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Application-Version", "12.34")
.addEntry("foo.jar", emptyInputStream());
props.setProperty("capsule.version", "");
Class<?> capsuleClass = loadCapsule(jar);
setProperties(capsuleClass, props);
StringPrintStream out = setSTDOUT(capsuleClass, new StringPrintStream());
Object capsule = newCapsule(capsuleClass);
boolean found = runActions(capsule, null);
String res = out.toString();
assert_().that(found).isTrue();
assert_().that(res).contains("Application com.acme.Foo_12.34");
assert_().that(res).contains("Version: 12.34");
}
@Test
public void testPrintModes() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("Application-Version", "12.34")
.setAttribute("ModeX", "System-Properties", "bar baz=55 foo=w")
.setAttribute("ModeX", "Description", "This is a secret mode")
.setAttribute("ModeY", "Description", "This is another secret mode")
.setAttribute("ModeZ", "Foo", "xxx")
.setAttribute("ModeX-Linux", "System-Properties", "bar baz=55 foo=w os=lin")
.setAttribute("ModeX-MacOS", "System-Properties", "bar baz=55 foo=w os=mac")
.setAttribute("ModeX-Windows", "System-Properties", "bar baz=55 foo=w os=win")
.setAttribute("ModeY-Java-15", "Description", "This is a secret mode")
.addEntry("foo.jar", emptyInputStream());
props.setProperty("capsule.modes", "");
Class<?> capsuleClass = loadCapsule(jar);
setProperties(capsuleClass, props);
StringPrintStream out = setSTDOUT(capsuleClass, new StringPrintStream());
Object capsule = newCapsule(capsuleClass);
boolean found = runActions(capsule, null);
String res = out.toString();
assert_().that(found).isTrue();
assert_().that(res).contains("* ModeX: This is a secret mode");
assert_().that(res).contains("* ModeY: This is another secret mode");
assert_().that(res).contains("* ModeZ");
assert_().that(res).doesNotContain("* ModeX-Linux");
assert_().that(res).doesNotContain("* ModeY-Java-15");
}
@Test
public void testMerge() throws Exception {
Jar wrapper = newCapsuleJar()
.setAttribute("Caplets", "MyCapsule")
.setAttribute("System-Properties", "p1=555")
.addClass(MyCapsule.class);
Jar app = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo")
.setAttribute("System-Properties", "p1=111")
.setListAttribute("App-Class-Path", list("lib/a.jar"))
.addClass(Capsule.class)
.addEntry("foo.jar", emptyInputStream())
.addEntry("a.class", emptyInputStream())
.addEntry("b.txt", emptyInputStream())
.addEntry("lib/a.jar", emptyInputStream())
.addEntry("lib/b.class", emptyInputStream())
.addEntry("META-INF/x.txt", emptyInputStream());
Class<?> capsuleClass = loadCapsule(wrapper);
// setProperties(capsuleClass, props);
Path fooPath = mockDep(capsuleClass, "com.acme:foo", "jar", "com.acme:foo:1.0").get(0);
Files.createDirectories(fooPath.getParent());
app.write(fooPath);
props.setProperty("capsule.merge", "out.jar");
// props.setProperty("capsule.log", "verbose");
int exit = main0(capsuleClass, "com.acme:foo");
assertEquals(0, exit);
assertTrue(Files.isRegularFile(path("out.jar")));
Jar out = new Jar(path("out.jar"));
assert_().that(out.getAttribute("Main-Class")).isEqualTo("TestCapsule");
assert_().that(out.getAttribute("Premain-Class")).isEqualTo("TestCapsule");
assert_().that(out.getListAttribute("Caplets")).isEqualTo(list("MyCapsule"));
assert_().that(out.getMapAttribute("System-Properties", "")).isEqualTo(map("p1", "111"));
FileSystem jar = ZipFS.newZipFileSystem(path("out.jar"));
assertTrue(Files.isRegularFile(jar.getPath("Capsule.class")));
assertTrue(Files.isRegularFile(jar.getPath("TestCapsule.class")));
assertTrue(Files.isRegularFile(jar.getPath("MyCapsule.class")));
assertTrue(Files.isRegularFile(jar.getPath("foo.jar")));
assertTrue(Files.isRegularFile(jar.getPath("a.class")));
assertTrue(Files.isRegularFile(jar.getPath("b.txt")));
assertTrue(Files.isRegularFile(jar.getPath("lib/a.jar")));
assertTrue(Files.isRegularFile(jar.getPath("lib/b.class")));
assertTrue(Files.isRegularFile(jar.getPath("META-INF/x.txt")));
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Unit Tests">
/////////// Unit Tests ///////////////////////////////////
@Test
public void testParseJavaVersion() {
int[] ver;
ver = Capsule.parseJavaVersion("8");
assertArrayEquals(ver, ints(1, 8, 0, 0, 0));
assertEquals("1.8.0", Capsule.toJavaVersionString(ver));
ver = Capsule.parseJavaVersion("1.8.0");
assertArrayEquals(ver, ints(1, 8, 0, 0, 0));
assertEquals("1.8.0", Capsule.toJavaVersionString(ver));
ver = Capsule.parseJavaVersion("1.8");
assertArrayEquals(ver, ints(1, 8, 0, 0, 0));
assertEquals("1.8.0", Capsule.toJavaVersionString(ver));
ver = Capsule.parseJavaVersion("1.8.0_30");
assertArrayEquals(ver, ints(1, 8, 0, 30, 0));
assertEquals("1.8.0_30", Capsule.toJavaVersionString(ver));
ver = Capsule.parseJavaVersion("1.8.0-rc");
assertArrayEquals(ver, ints(1, 8, 0, 0, -1));
assertEquals("1.8.0-rc", Capsule.toJavaVersionString(ver));
ver = Capsule.parseJavaVersion("1.8.0_30-ea");
assertArrayEquals(ver, ints(1, 8, 0, 30, -3));
assertEquals("1.8.0_30-ea", Capsule.toJavaVersionString(ver));
}
@Test
public void testCompareVersions() {
assertTrue(Capsule.compareVersions("1.8.0_30-ea", "1.8.0_30") < 0);
assertTrue(Capsule.compareVersions("1.8.0_30-ea", "1.8.0_20") > 0);
assertTrue(Capsule.compareVersions("1.8.0-ea", "1.8.0_20") < 0);
assertTrue(Capsule.compareVersions("1.8.0-ea", "1.8.0") < 0);
assertTrue(Capsule.compareVersions("1.8.0-ea", "1.7.0") > 0);
}
@Test
public void testShortJavaVersion() {
assertEquals("1.8.0", Capsule.shortJavaVersion("8"));
assertEquals("1.8.0", Capsule.shortJavaVersion("1.8"));
assertEquals("1.8.0", Capsule.shortJavaVersion("1.8.0"));
}
@Test
public void isJavaDir() {
assertEquals("1.7.0", Capsule.isJavaDir("jre7"));
assertEquals("1.7.0_45", Capsule.isJavaDir("jdk1.7.0_45"));
assertEquals("1.7.0_51", Capsule.isJavaDir("jdk1.7.0_51.jdk"));
assertEquals("1.7.0", Capsule.isJavaDir("1.7.0.jdk"));
assertEquals("1.8.0", Capsule.isJavaDir("jdk1.8.0.jdk"));
assertEquals("1.7.0", Capsule.isJavaDir("java-7-openjdk-amd64"));
assertEquals("1.7.0", Capsule.isJavaDir("java-1.7.0-openjdk-amd64"));
assertEquals("1.7.0", Capsule.isJavaDir("java-1.7.0-openjdk-1.7.0.79.x86_64"));
assertEquals("1.8.0", Capsule.isJavaDir("java-8-oracle"));
assertEquals("1.8.0", Capsule.isJavaDir("jdk-8-oracle"));
assertEquals("1.8.0", Capsule.isJavaDir("jre-8-oracle"));
assertEquals("1.8.0", Capsule.isJavaDir("jdk-8-oracle-x64"));
assertEquals("1.8.0", Capsule.isJavaDir("jdk-1.8.0"));
assertEquals("1.8.0", Capsule.isJavaDir("jre-1.8.0"));
}
@Test
public void testDelete() throws Exception {
Files.createDirectories(path("a", "b", "c"));
Files.createDirectories(path("a", "b1"));
Files.createDirectories(path("a", "b", "c1"));
Files.createFile(path("a", "x"));
Files.createFile(path("a", "b", "x"));
Files.createFile(path("a", "b1", "x"));
Files.createFile(path("a", "b", "c", "x"));
Files.createFile(path("a", "b", "c1", "x"));
assertTrue(Files.exists(path("a")));
assertTrue(Files.isDirectory(path("a")));
//Files.delete(path("a"));
Capsule.delete(path("a"));
assertTrue(!Files.exists(path("a")));
}
@Test
public void testGlobToRegex() throws Exception {
assertEquals(true, "abc/def".matches(Capsule.globToRegex("abc/def")));
assertEquals(true, "abc/def".matches(Capsule.globToRegex("*/d*")));
assertEquals(true, "abc/def".matches(Capsule.globToRegex("a*/d*")));
assertEquals(true, "abc/def".matches(Capsule.globToRegex("*/*")));
assertEquals(false, "abc/def".matches(Capsule.globToRegex("abc/d")));
assertEquals(false, "abc/def".matches(Capsule.globToRegex("*")));
assertEquals(false, "abc/def".matches(Capsule.globToRegex("d*")));
assertEquals(false, "abc/def".matches(Capsule.globToRegex("abc?d*")));
}
@Test
public void testParseCommandLineArguments() throws Exception {
assertEquals(list("x", "y", "z"), Capsule.parseCommandLineArguments("x y z"));
assertEquals(list("x", "y z"), Capsule.parseCommandLineArguments("x 'y z'"));
assertEquals(list("x y", "z"), Capsule.parseCommandLineArguments("\"x y\" z"));
}
@Test
public void testMove() throws Exception {
assertEquals(Paths.get("/c/d"), Capsule.move(Paths.get("/a/b"), Paths.get("/a/b"), Paths.get("/c/d/")));
assertEquals(Paths.get("/c/d/e"), Capsule.move(Paths.get("/a/b/e"), Paths.get("/a/b"), Paths.get("/c/d/")));
}
@Test
public void testDependencyToLocalJar() throws Exception {
Path jar = fs.getPath("foo.jar");
String file;
file = "lib/com.acme/foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "lib/com.acme-foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "lib/com.acme-foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "lib/com.acme-foo-3.1-big.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1:big", "mmm"));
file = "lib/foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "com.acme/foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "com.acme-foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "com.acme-foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
file = "com.acme-foo-3.1-big.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1:big", "mmm"));
file = "foo-3.1.mmm";
writeJarWithFile(jar, file);
assertEquals(file, dependencyToLocalJar(jar, "com.acme:foo:3.1", "mmm"));
}
private Path writeJarWithFile(Path path, String... entries) throws IOException {
Jar jar = newCapsuleJar();
for (String entry : entries)
jar.addEntry(entry, emptyInputStream());
jar.write(path);
return path;
}
private static void clearCaches() {
Reflect.on(Capsule.class).call("clearCaches");
}
private static String dependencyToLocalJar(Path jar, String dep, String type) {
clearCaches();
return Reflect.on(Capsule.class).call("dependencyToLocalJar0", jar, dep, type, null).get();
}
@Test
public void testExpandVars1() throws Exception {
Jar jar = newCapsuleJar()
.setAttribute("Application-Class", "com.acme.Foo");
props.setProperty("a.b.c", "777");
props.setProperty("my.prop", "888");
Capsule capsule = newCapsule(jar);
capsule.prepareForLaunch(null, null);
String cj = absolutePath("capsule.jar").toString();
String cd = cache.resolve("apps").resolve("com.acme.Foo").toString();
String cid = capsule.getAppId();
assertEquals(cj + "abc" + cj + "def " + cj, expand(capsule, "${CAPSULE_JAR}" + "abc" + "${CAPSULE_JAR}" + "def" + " $CAPSULE_JAR"));
assertEquals(cid + " abc" + cid + "def" + cid, expand(capsule, "$CAPSULE_APP" + " abc" + "${CAPSULE_APP}" + "def" + "${CAPSULE_APP}"));
assertEquals(cd + "abc " + cd + " def" + cd, expand(capsule, "${CAPSULE_DIR}" + "abc " + "$CAPSULE_DIR" + " def" + "${CAPSULE_DIR}"));
assertEquals(cd + "abc" + cid + "def" + cj + "888777", expand(capsule, "${CAPSULE_DIR}" + "abc" + "${CAPSULE_APP}" + "def" + "${CAPSULE_JAR}${my.prop}${a.b.c}"));
assertEquals("888", expand(capsule, "${my.prop}"));
assertEquals(cj, expand(capsule, "$CAPSULE_JAR"));
try {
expand(capsule, "${foo.bar.baz}");
fail();
} catch (RuntimeException e) {
}
}
private String expand(Capsule c, String s) {
return Reflect.on(c).call("expand", s).get();
}
@Test
public void testExpandArgs() throws Exception {
assertEquals(list("x", "y", "z"), Capsule.expandArgs(list("x", "y", "z"), CapsuleTest.<String>list()));
assertEquals(list("a", "b", "c"), Capsule.expandArgs(CapsuleTest.<String>list(), list("a", "b", "c")));
assertEquals(list("x", "y", "z", "a", "b", "c"), Capsule.expandArgs(list("x", "y", "z"), list("a", "b", "c")));
assertEquals(list("x", "a", "b", "c", "z"), Capsule.expandArgs(list("x", "$*", "z"), list("a", "b", "c")));
assertEquals(list("b", "a", "c"), Capsule.expandArgs(list("$2", "$1", "$3"), list("a", "b", "c")));
}
@Test
public void testParseAttribute() {
assertEquals("abcd 123", Capsule.parse("abcd 123", Capsule.T_STRING(), null));
assertEquals(true, Capsule.parse("TRUE", Capsule.T_BOOL(), null));
assertEquals(true, Capsule.parse("true", Capsule.T_BOOL(), null));
assertEquals(false, Capsule.parse("FALSE", Capsule.T_BOOL(), null));
assertEquals(false, Capsule.parse("false", Capsule.T_BOOL(), null));
assertEquals(15L, (long) Capsule.parse("15", Capsule.T_LONG(), null));
try {
Capsule.parse("15abs", Capsule.T_LONG(), null);
fail();
} catch (RuntimeException e) {
}
assertEquals(1.2, Capsule.parse("1.2", Capsule.T_DOUBLE(), null), 0.0001);
try {
Capsule.parse("1.2a", Capsule.T_DOUBLE(), null);
fail();
} catch (RuntimeException e) {
}
assertEquals(list("abcd", "123"), Capsule.parse("abcd 123", Capsule.T_LIST(Capsule.T_STRING()), null));
assertEquals(list("ab", "cd", "ef", "g", "hij", "kl"), Capsule.parse("ab cd ef g hij kl ", Capsule.T_LIST(Capsule.T_STRING()), null));
assertEquals(list(true, false, true, false), Capsule.parse("TRUE false true FALSE", Capsule.T_LIST(Capsule.T_BOOL()), null));
assertEquals(list(123L, 456L, 7L), Capsule.parse("123 456 7", Capsule.T_LIST(Capsule.T_LONG()), null));
assertEquals(list(1.23, 3.45), Capsule.parse("1.23 3.45", Capsule.T_LIST(Capsule.T_DOUBLE()), null));
assertEquals(map("ab", "1",
"cd", "xx",
"ef", "32",
"g", "xx",
"hij", "",
"kl", ""), Capsule.parse("ab=1 cd ef=32 g hij= kl= ", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_STRING(), "xx"), null));
try {
Capsule.parse("ab=1 cd ef=32 g hij= kl= ", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_STRING(), null), null);
fail();
} catch (Exception e) {
}
assertEquals(map("ab", true, "cd", true, "ef", false, "g", true), Capsule.parse("ab=true cd ef=false g", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_BOOL(), true), null));
try {
Capsule.parse("ab=true cd ef=false g", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_BOOL(), null), null);
fail();
} catch (Exception e) {
}
assertEquals(map("ab", 12L, "cd", 17L, "ef", 54L, "g", 17L), Capsule.parse("ab=12 cd ef=54 g", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_LONG(), 17), null));
try {
Capsule.parse("ab=12 cd ef=54 g", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_LONG(), null), null);
fail();
} catch (Exception e) {
}
try {
Capsule.parse("ab=12 cd=xy ef=54 g=z", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_LONG(), 17), null);
fail();
} catch (Exception e) {
}
assertEquals(map("ab", 12.0, "cd", 100.0, "ef", 5.4, "g", 100.0), Capsule.parse("ab=12 cd ef=5.4 g", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_DOUBLE(), 100), null));
try {
Capsule.parse("ab=12.1 cd ef=5.4 g", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_DOUBLE(), null), null);
fail();
} catch (Exception e) {
}
try {
Capsule.parse("ab=12 cd=xy ef=54 g=z", Capsule.T_MAP(Capsule.T_STRING(), Capsule.T_DOUBLE(), 17.0), null);
fail();
} catch (Exception e) {
}
assertEquals(map(12.3, 12L, 1.01, 17L, 2.05, 54L, 4.0, 17L), Capsule.parse("12.3=12 1.01 2.05=54 4.0", Capsule.T_MAP(Capsule.T_DOUBLE(), Capsule.T_LONG(), 17), null));
}
@Test
@SuppressWarnings("deprecation")
public void testPathingJar() throws Exception {
Files.createDirectories(tmp);
List<Path> cp = list(path("/a.jar"), path("/b.jar"), path("/c.jar"));
Path pathingJar = Capsule.createPathingJar(tmp, cp);
try {
List<Path> cp2;
try (JarInputStream jis = new JarInputStream(Files.newInputStream(pathingJar))) {
cp2 = toPath(Arrays.asList(jis.getManifest().getMainAttributes().getValue("Class-Path").split(" ")));
}
assertEquals(cp, toAbsolutePath(cp2));
for (Path p : cp2)
assertTrue(!p.isAbsolute());
} finally {
Files.delete(pathingJar);
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Utilities">
/////////// Utilities ///////////////////////////////////
// may be called once per test (always writes jar into /capsule.jar)
private Capsule newCapsule(Jar jar) {
return (Capsule) CapsuleTestUtils.newCapsule(jar, path("capsule.jar"));
}
private Class<?> loadCapsule(Jar jar) throws IOException {
jar = makeRealCapsuleJar(jar);
Class<?> clazz = CapsuleTestUtils.loadCapsule(jar, path("capsule.jar"));
setProperties(clazz, props);
setCacheDir(clazz, cache);
return clazz;
}
private Object newCapsule(Class<?> capsuleClass) {
return CapsuleTestUtils.newCapsule(capsuleClass, path("capsule.jar"));
}
private Jar newCapsuleJar() {
return new Jar()
.setAttribute("Manifest-Version", "1.0")
.setAttribute("Main-Class", "TestCapsule")
.setAttribute("Premain-Class", "TestCapsule")
.setAttribute("Capsule-Agent", "true");
}
private Jar makeRealCapsuleJar(Jar jar) throws IOException {
return jar.addClass(Capsule.class)
.addClass(TestCapsule.class);
}
private Capsule setTarget(Capsule capsule, String artifact) {
return Reflect.on(capsule).call("setTarget", artifact).get();
}
private Capsule setTarget(Capsule capsule, Path jar) {
return Reflect.on(capsule).call("setTarget", jar).get();
}
private Path path(String first, String... more) {
return fs.getPath(first, more);
}
private Path absolutePath(String first, String... more) {
return fs.getPath(first, more).toAbsolutePath();
}
private InputStream emptyInputStream() {
return Jar.toInputStream("", UTF_8);
}
private List<Path> paths(String cp) {
final List<Path> res = new ArrayList<>();
for (String p : cp.split(":"))
res.add(path(p));
return res;
}
private List<Path> getClassPath(ProcessBuilder pb) {
final List<String> cmd = pb.command();
final int i = cmd.indexOf("-classpath");
if (i < 0)
return null;
final String cp = cmd.get(i + 1);
// return Arrays.asList(cp.split(":"));
return paths(cp);
}
private String getProperty(ProcessBuilder pb, String prop) {
return getOption(pb, "-D" + prop, '=');
}
private String getEnv(ProcessBuilder pb, String envVar) {
return pb.environment().get(envVar);
}
private String getOption(ProcessBuilder pb, String opt) {
return getOption(pb, opt, ':');
}
private String getOption(ProcessBuilder pb, String opt, char separator) {
final List<String> jvmargs = getJvmArgs(pb);
for (String a : jvmargs) {
if (a.startsWith(opt)) {
String res = getAfter(a, separator);
return res != null ? res : "";
}
}
return null;
}
private List<String> getJvmArgs(ProcessBuilder pb) {
boolean classpath = false;
int i = 0;
for (String x : pb.command().subList(1, pb.command().size())) {
if (x.equals("-jar") || (!x.startsWith("-") && !classpath))
break;
if (x.equals("-classpath") || x.equals("-cp"))
classpath = true;
else
classpath = false;
i++;
}
return pb.command().subList(1, i + 1);
}
private String getMainJar(ProcessBuilder pb) {
final List<String> cmd = pb.command();
final int start = getJvmArgs(pb).size() + 1;
if (cmd.get(start).equals("-jar"))
return cmd.get(start + 1);
return null;
}
private String getMainClass(ProcessBuilder pb) {
final List<String> cmd = pb.command();
final int start = getJvmArgs(pb).size() + 1;
if (cmd.get(start).equals("-jar"))
return null;
return cmd.get(start);
}
private List<String> getAppArgs(ProcessBuilder pb) {
List<String> jvmArgs = getJvmArgs(pb);
final List<String> cmd = pb.command();
final int start = jvmArgs.size() + 1;
return cmd.subList(start + (cmd.get(start).equals("-jar") ? 2 : 1), cmd.size());
}
private static List<String> getMainAndArgs(ProcessBuilder pb) {
List<String> cmd = pb.command();
cmd = cmd.subList(1, cmd.size());
boolean prevClassPath = false;
int i = 0;
for (String c : cmd) {
if (c.startsWith("-") || prevClassPath)
i++;
else
break;
prevClassPath = c.equals("-classpath");
}
return cmd.subList(i, cmd.size());
}
private List<Path> toPath(List<String> ps) {
final List<Path> pss = new ArrayList<Path>(ps.size());
for (String p : ps)
pss.add(path(p));
return pss;
}
private List<Path> toAbsolutePath(List<Path> ps) {
final List<Path> pss = new ArrayList<Path>(ps.size());
for (Path p : ps)
pss.add(p.toAbsolutePath().normalize());
return pss;
}
private static String getBefore(String s, char separator) {
final int i = s.indexOf(separator);
if (i < 0)
return s;
return s.substring(0, i);
}
private static String getAfter(String s, char separator) {
final int i = s.indexOf(separator);
if (i < 0)
return null;
return s.substring(i + 1);
}
private static <T extends Comparable<? super T>> List<T> sort(List<T> list) {
final List<T> c = new ArrayList<>(list);
Collections.<T>sort(c);
return c;
}
private static <T> Set<T> set(Collection<T> list) {
return new HashSet<>(list);
}
@SafeVarargs
private static <T> List<T> list(T... xs) {
return Arrays.asList(xs);
}
@SafeVarargs
private static <T> Set<T> set(T... xs) {
return set(Arrays.asList(xs));
}
private static String[] strings(String... xs) {
return xs;
}
private static int[] ints(int... xs) {
return xs;
}
@SuppressWarnings("unchecked")
private static <K, V> Map<K, V> map(Object... ss) {
final Map<K, V> m = new HashMap<>();
for (int i = 0; i < ss.length / 2; i++)
m.put((K) ss[i * 2], (V) ss[i * 2 + 1]);
return Collections.unmodifiableMap(m);
}
private Path mockDep(String dep, String type) {
return mockDep(dep, type, dep).get(0);
}
private List<Path> mockDep(String dep, String type, String... artifacts) {
return mockDep(TestCapsule.class, dep, type, artifacts);
}
private List<Path> mockDep(Class<?> testCapsuleClass, String dep, String type, String... artifacts) {
List<Path> as = new ArrayList<>(artifacts.length);
for (String a : artifacts)
as.add(artifact(a, type));
try {
testCapsuleClass.getMethod("mock", String.class, String.class, List.class).invoke(null, dep, type, as);
} catch (ReflectiveOperationException e) {
throw rethrow(e);
}
return as;
}
private Path artifact(String x, String type) {
String[] coords = x.split(":");
String group = coords[0];
String artifact = coords[1];
String artifactDir = artifact.split("-")[0]; // arbitrary
String version = coords[2] + (coords.length > 3 ? "-" + coords[3] : "");
return cache.resolve("deps").resolve(group).resolve(artifactDir).resolve(artifact + "-" + version + '.' + type);
}
private static void dumpFileSystem(FileSystem fs) {
try {
Files.walkFileTree(fs.getRootDirectories().iterator().next(), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("-- " + file);
return super.visitFile(file, attrs);
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static final String PS = System.getProperty("path.separator");
//</editor-fold>
}