Skip to content

Commit 369f23e

Browse files
author
Anthony Keenan
authored
CORDA-1817: Fix issue with misleading capsule error messages (corda#4215)
* Make caplet respect all acceptable combinations of cmd line parameters * If cordapp dir fails to create, still run corda.jar and let it fail gracefully * Don't parse additional options as the parameter for the previous one. * Remove commented lines
1 parent bb0ed9e commit 369f23e

7 files changed

+212
-7
lines changed

node/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ dependencies {
151151
// Capsule is a library for building independently executable fat JARs.
152152
// We only need this dependency to compile our Caplet against.
153153
compileOnly "co.paralleluniverse:capsule:$capsule_version"
154+
testCompile "co.paralleluniverse:capsule:$capsule_version"
154155

155156
// OkHTTP: Simple HTTP library.
156157
compile "com.squareup.okhttp3:okhttp:$okhttp_version"

node/src/main/java/CordaCaplet.java

+37-7
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ protected CordaCaplet(Capsule pred) {
2020
}
2121

2222
private Config parseConfigFile(List<String> args) {
23-
String baseDirOption = getOption(args, "--base-directory");
24-
this.baseDir = Paths.get((baseDirOption == null) ? "." : baseDirOption).toAbsolutePath().normalize().toString();
23+
this.baseDir = getBaseDirectory(args);
2524
String config = getOption(args, "--config-file");
2625
File configFile = (config == null) ? new File(baseDir, "node.conf") : new File(config);
2726
try {
@@ -36,17 +35,44 @@ private Config parseConfigFile(List<String> args) {
3635
}
3736
}
3837

38+
File getConfigFile(List<String> args, String baseDir) {
39+
String config = getOptionMultiple(args, Arrays.asList("--config-file", "-f"));
40+
return (config == null || config.equals("")) ? new File(baseDir, "node.conf") : new File(config);
41+
}
42+
43+
String getBaseDirectory(List<String> args) {
44+
String baseDir = getOptionMultiple(args, Arrays.asList("--base-directory", "-b"));
45+
return Paths.get((baseDir == null) ? "." : baseDir).toAbsolutePath().normalize().toString();
46+
}
47+
48+
private String getOptionMultiple(List<String> args, List<String> possibleOptions) {
49+
String result = null;
50+
for(String option: possibleOptions) {
51+
result = getOption(args, option);
52+
if (result != null) break;
53+
}
54+
return result;
55+
}
56+
3957
private String getOption(List<String> args, String option) {
4058
final String lowerCaseOption = option.toLowerCase();
4159
int index = 0;
4260
for (String arg : args) {
4361
if (arg.toLowerCase().equals(lowerCaseOption)) {
44-
if (index < args.size() - 1) {
62+
if (index < args.size() - 1 && !args.get(index + 1).startsWith("-")) {
4563
return args.get(index + 1);
4664
} else {
4765
return null;
4866
}
4967
}
68+
69+
if (arg.toLowerCase().startsWith(lowerCaseOption)) {
70+
if (arg.length() > option.length() && arg.substring(option.length(), option.length() + 1).equals("=")) {
71+
return arg.substring(option.length() + 1);
72+
} else {
73+
return null;
74+
}
75+
}
5076
index++;
5177
}
5278
return null;
@@ -82,7 +108,10 @@ protected <T> T attribute(Map.Entry<String, T> attr) {
82108

83109
File cordappsDir = new File(baseDir, "cordapps");
84110
// Create cordapps directory if it doesn't exist.
85-
requireCordappsDirExists(cordappsDir);
111+
if (!checkIfCordappDirExists(cordappsDir)) {
112+
// If it fails, just return the existing class path. The main Corda jar will detect the error and fail gracefully.
113+
return cp;
114+
}
86115
// Add additional directories of JARs to the classpath (at the end), e.g., for JDBC drivers.
87116
augmentClasspath((List<Path>) cp, cordappsDir);
88117
try {
@@ -152,17 +181,18 @@ private static void checkJavaVersion() {
152181
}
153182
}
154183

155-
private void requireCordappsDirExists(File dir) {
184+
private Boolean checkIfCordappDirExists(File dir) {
156185
try {
157186
if (!dir.mkdir() && !dir.exists()) { // It is unlikely to enter this if-branch, but just in case.
158187
logOnFailedCordappDir();
159-
throw new RuntimeException("Cordapps dir could not be created"); // Let Capsule handle the error (log error, clean up, die).
188+
return false;
160189
}
161190
}
162191
catch (SecurityException | NullPointerException e) {
163192
logOnFailedCordappDir();
164-
throw e; // Let Capsule handle the error (log error, clean up, die).
193+
return false;
165194
}
195+
return true;
166196
}
167197

168198
private void logOnFailedCordappDir() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import org.junit.Test;
2+
import org.junit.runner.RunWith;
3+
import org.junit.runners.Parameterized;
4+
5+
import java.nio.file.Paths;
6+
import java.util.Arrays;
7+
import java.util.Collection;
8+
9+
import static org.junit.Assert.assertEquals;
10+
11+
@RunWith(Parameterized.class)
12+
public class CordaCapletBaseDirectoryParsingFailureTest {
13+
@Parameterized.Parameters
14+
public static Collection<Object[]> CombinationsToTest() {
15+
return Arrays.asList(
16+
new Object[][]{
17+
{new String[]{"--base-directory", "--another-option"}},
18+
{new String[]{"--base-directory=", "-a"}},
19+
{new String[]{"-b", "--another-option"}},
20+
{new String[]{"-b=", "-a"}}
21+
}
22+
);
23+
}
24+
25+
private String[] cmdLineArguments;
26+
27+
public CordaCapletBaseDirectoryParsingFailureTest(String[] baseOption) {
28+
this.cmdLineArguments = baseOption;
29+
}
30+
31+
@Test
32+
public void testThatBaseDirectoryFallsBackToCurrentWhenBaseDirectoryIsNotSupplied() {
33+
final CordaCaplet caplet = CordaCapletTestUtils.getCaplet();
34+
final String returnPath = caplet.getBaseDirectory(Arrays.asList(cmdLineArguments));
35+
final String expected = Paths.get(".").toAbsolutePath().normalize().toString();
36+
assertEquals(expected, returnPath);
37+
}
38+
}
39+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
import org.junit.Test;
3+
import org.junit.runner.RunWith;
4+
import org.junit.runners.Parameterized;
5+
6+
import java.nio.file.Paths;
7+
import java.util.Arrays;
8+
import java.util.Collection;
9+
10+
import static org.junit.Assert.assertEquals;
11+
12+
@RunWith(Parameterized.class)
13+
public class CordaCapletBaseDirectoryParsingTest {
14+
@Parameterized.Parameters
15+
public static Collection<Object[]> CombinationsToTest() {
16+
return Arrays.asList(
17+
new Object[][]{
18+
{new String[]{"--base-directory", "blah"}},
19+
{new String[]{"--base-directory=blah"}},
20+
{new String[]{"-b", "blah"}},
21+
{new String[]{"-b=blah"}}
22+
});
23+
}
24+
25+
private String[] cmdLineArguments;
26+
27+
public CordaCapletBaseDirectoryParsingTest(String[] arr) {
28+
this.cmdLineArguments = arr;
29+
}
30+
31+
@Test
32+
public void testThatBaseDirectoryParameterIsRecognised() {
33+
final CordaCaplet caplet = CordaCapletTestUtils.getCaplet();
34+
final String returnPath = caplet.getBaseDirectory(Arrays.asList(cmdLineArguments));
35+
final String expected = Paths.get(".").resolve("blah").toAbsolutePath().normalize().toString();
36+
assertEquals(expected, returnPath);
37+
}
38+
}
39+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import org.junit.Test;
2+
import org.junit.runner.RunWith;
3+
import org.junit.runners.Parameterized;
4+
5+
import java.io.File;
6+
import java.nio.file.Paths;
7+
import java.util.Arrays;
8+
import java.util.Collection;
9+
10+
import static org.junit.Assert.assertEquals;
11+
12+
@RunWith(Parameterized.class)
13+
public class CordaCapletConfigFileParsingFailureTest {
14+
@Parameterized.Parameters
15+
public static Collection<Object[]> CombinationsToTest() {
16+
return Arrays.asList(
17+
new Object[][]{
18+
{new String[]{"--config-file", "--another-option"}},
19+
{new String[]{"--config-file=", "-a"}},
20+
{new String[]{"-f", "--another-option"}},
21+
{new String[]{"-f=", "-a"}}
22+
}
23+
);
24+
}
25+
26+
private String[] cmdLineArguments;
27+
28+
public CordaCapletConfigFileParsingFailureTest(String[] baseOption) {
29+
this.cmdLineArguments = baseOption;
30+
}
31+
32+
@Test
33+
public void testThatBaseDirectoryFallsBackToDefaultWhenConfigFileIsNotSupplied() {
34+
final CordaCaplet caplet = CordaCapletTestUtils.getCaplet();
35+
final File returnPath = caplet.getConfigFile(Arrays.asList(cmdLineArguments), CordaCapletTestUtils.getBaseDir());
36+
final File expected = Paths.get(".").resolve("node.conf").toAbsolutePath().normalize().toFile();
37+
assertEquals(expected, returnPath);
38+
}
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
import org.junit.Test;
3+
import org.junit.runner.RunWith;
4+
import org.junit.runners.Parameterized;
5+
6+
import java.io.File;
7+
import java.nio.file.Paths;
8+
import java.util.Arrays;
9+
import java.util.Collection;
10+
11+
import static org.junit.Assert.assertEquals;
12+
13+
@RunWith(Parameterized.class)
14+
public class CordaCapletConfigFileParsingTest {
15+
@Parameterized.Parameters
16+
public static Collection<Object[]> CombinationsToTest() {
17+
return Arrays.asList(
18+
new Object[][]{
19+
{new String[]{"--config-file", "blah.conf"}},
20+
{new String[]{"--config-file=blah.conf"}},
21+
{new String[]{"-f", "blah.conf"}},
22+
{new String[]{"-f=blah.conf"}}
23+
});
24+
}
25+
26+
private String[] cmdLineArguments;
27+
28+
public CordaCapletConfigFileParsingTest(String[] arr) {
29+
this.cmdLineArguments = arr;
30+
}
31+
32+
@Test
33+
public void testThatConfigFileParameterIsRecognised() {
34+
final CordaCaplet caplet = CordaCapletTestUtils.getCaplet();
35+
final File returnPath = caplet.getConfigFile(Arrays.asList(cmdLineArguments), CordaCapletTestUtils.getBaseDir());
36+
final File expected = Paths.get(".").resolve("blah.conf").toAbsolutePath().normalize().toFile();
37+
assertEquals(expected, returnPath.getAbsoluteFile());
38+
}
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import java.io.File;
2+
import java.nio.file.Paths;
3+
import java.util.Arrays;
4+
import java.util.Objects;
5+
6+
class CordaCapletTestUtils {
7+
static CordaCaplet getCaplet() {
8+
final String path = System.getProperty("user.dir") + File.separator + "build" + File.separator + "libs" + File.separator;
9+
final File jar = Arrays.stream(Objects.requireNonNull(new File(path).listFiles())).filter(x -> x.getName().startsWith("corda-node") && x.getName().endsWith(".jar")).findFirst().get();
10+
return new CordaCaplet(new Capsule(jar.toPath()));
11+
}
12+
13+
static String getBaseDir() {
14+
return Paths.get(".").toAbsolutePath().normalize().toString();
15+
}
16+
}

0 commit comments

Comments
 (0)