diff --git a/node/build.gradle b/node/build.gradle index 8528de21a4..e540562221 100644 --- a/node/build.gradle +++ b/node/build.gradle @@ -151,6 +151,7 @@ dependencies { // Capsule is a library for building independently executable fat JARs. // We only need this dependency to compile our Caplet against. compileOnly "co.paralleluniverse:capsule:$capsule_version" + testCompile "co.paralleluniverse:capsule:$capsule_version" // OkHTTP: Simple HTTP library. compile "com.squareup.okhttp3:okhttp:$okhttp_version" diff --git a/node/src/main/java/CordaCaplet.java b/node/src/main/java/CordaCaplet.java index da1e3b9ce4..78ccce99af 100644 --- a/node/src/main/java/CordaCaplet.java +++ b/node/src/main/java/CordaCaplet.java @@ -20,8 +20,7 @@ public class CordaCaplet extends Capsule { } private Config parseConfigFile(List args) { - String baseDirOption = getOption(args, "--base-directory"); - this.baseDir = Paths.get((baseDirOption == null) ? "." : baseDirOption).toAbsolutePath().normalize().toString(); + this.baseDir = getBaseDirectory(args); String config = getOption(args, "--config-file"); File configFile = (config == null) ? new File(baseDir, "node.conf") : new File(config); try { @@ -36,17 +35,44 @@ public class CordaCaplet extends Capsule { } } + File getConfigFile(List args, String baseDir) { + String config = getOptionMultiple(args, Arrays.asList("--config-file", "-f")); + return (config == null || config.equals("")) ? new File(baseDir, "node.conf") : new File(config); + } + + String getBaseDirectory(List args) { + String baseDir = getOptionMultiple(args, Arrays.asList("--base-directory", "-b")); + return Paths.get((baseDir == null) ? "." : baseDir).toAbsolutePath().normalize().toString(); + } + + private String getOptionMultiple(List args, List possibleOptions) { + String result = null; + for(String option: possibleOptions) { + result = getOption(args, option); + if (result != null) break; + } + return result; + } + private String getOption(List args, String option) { final String lowerCaseOption = option.toLowerCase(); int index = 0; for (String arg : args) { if (arg.toLowerCase().equals(lowerCaseOption)) { - if (index < args.size() - 1) { + if (index < args.size() - 1 && !args.get(index + 1).startsWith("-")) { return args.get(index + 1); } else { return null; } } + + if (arg.toLowerCase().startsWith(lowerCaseOption)) { + if (arg.length() > option.length() && arg.substring(option.length(), option.length() + 1).equals("=")) { + return arg.substring(option.length() + 1); + } else { + return null; + } + } index++; } return null; @@ -82,7 +108,10 @@ public class CordaCaplet extends Capsule { File cordappsDir = new File(baseDir, "cordapps"); // Create cordapps directory if it doesn't exist. - requireCordappsDirExists(cordappsDir); + if (!checkIfCordappDirExists(cordappsDir)) { + // If it fails, just return the existing class path. The main Corda jar will detect the error and fail gracefully. + return cp; + } // Add additional directories of JARs to the classpath (at the end), e.g., for JDBC drivers. augmentClasspath((List) cp, cordappsDir); try { @@ -152,17 +181,18 @@ public class CordaCaplet extends Capsule { } } - private void requireCordappsDirExists(File dir) { + private Boolean checkIfCordappDirExists(File dir) { try { if (!dir.mkdir() && !dir.exists()) { // It is unlikely to enter this if-branch, but just in case. logOnFailedCordappDir(); - throw new RuntimeException("Cordapps dir could not be created"); // Let Capsule handle the error (log error, clean up, die). + return false; } } catch (SecurityException | NullPointerException e) { logOnFailedCordappDir(); - throw e; // Let Capsule handle the error (log error, clean up, die). + return false; } + return true; } private void logOnFailedCordappDir() { diff --git a/node/src/test/java/CordaCapletBaseDirectoryParsingFailureTest.java b/node/src/test/java/CordaCapletBaseDirectoryParsingFailureTest.java new file mode 100644 index 0000000000..21c672d2e2 --- /dev/null +++ b/node/src/test/java/CordaCapletBaseDirectoryParsingFailureTest.java @@ -0,0 +1,39 @@ +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class CordaCapletBaseDirectoryParsingFailureTest { + @Parameterized.Parameters + public static Collection CombinationsToTest() { + return Arrays.asList( + new Object[][]{ + {new String[]{"--base-directory", "--another-option"}}, + {new String[]{"--base-directory=", "-a"}}, + {new String[]{"-b", "--another-option"}}, + {new String[]{"-b=", "-a"}} + } + ); + } + + private String[] cmdLineArguments; + + public CordaCapletBaseDirectoryParsingFailureTest(String[] baseOption) { + this.cmdLineArguments = baseOption; + } + + @Test + public void testThatBaseDirectoryFallsBackToCurrentWhenBaseDirectoryIsNotSupplied() { + final CordaCaplet caplet = CordaCapletTestUtils.getCaplet(); + final String returnPath = caplet.getBaseDirectory(Arrays.asList(cmdLineArguments)); + final String expected = Paths.get(".").toAbsolutePath().normalize().toString(); + assertEquals(expected, returnPath); + } +} + diff --git a/node/src/test/java/CordaCapletBaseDirectoryParsingTest.java b/node/src/test/java/CordaCapletBaseDirectoryParsingTest.java new file mode 100644 index 0000000000..489e59f3e5 --- /dev/null +++ b/node/src/test/java/CordaCapletBaseDirectoryParsingTest.java @@ -0,0 +1,39 @@ + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class CordaCapletBaseDirectoryParsingTest { + @Parameterized.Parameters + public static Collection CombinationsToTest() { + return Arrays.asList( + new Object[][]{ + {new String[]{"--base-directory", "blah"}}, + {new String[]{"--base-directory=blah"}}, + {new String[]{"-b", "blah"}}, + {new String[]{"-b=blah"}} + }); + } + + private String[] cmdLineArguments; + + public CordaCapletBaseDirectoryParsingTest(String[] arr) { + this.cmdLineArguments = arr; + } + + @Test + public void testThatBaseDirectoryParameterIsRecognised() { + final CordaCaplet caplet = CordaCapletTestUtils.getCaplet(); + final String returnPath = caplet.getBaseDirectory(Arrays.asList(cmdLineArguments)); + final String expected = Paths.get(".").resolve("blah").toAbsolutePath().normalize().toString(); + assertEquals(expected, returnPath); + } +} + diff --git a/node/src/test/java/CordaCapletConfigFileParsingFailureTest.java b/node/src/test/java/CordaCapletConfigFileParsingFailureTest.java new file mode 100644 index 0000000000..b94e137eb5 --- /dev/null +++ b/node/src/test/java/CordaCapletConfigFileParsingFailureTest.java @@ -0,0 +1,40 @@ +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class CordaCapletConfigFileParsingFailureTest { + @Parameterized.Parameters + public static Collection CombinationsToTest() { + return Arrays.asList( + new Object[][]{ + {new String[]{"--config-file", "--another-option"}}, + {new String[]{"--config-file=", "-a"}}, + {new String[]{"-f", "--another-option"}}, + {new String[]{"-f=", "-a"}} + } + ); + } + + private String[] cmdLineArguments; + + public CordaCapletConfigFileParsingFailureTest(String[] baseOption) { + this.cmdLineArguments = baseOption; + } + + @Test + public void testThatBaseDirectoryFallsBackToDefaultWhenConfigFileIsNotSupplied() { + final CordaCaplet caplet = CordaCapletTestUtils.getCaplet(); + final File returnPath = caplet.getConfigFile(Arrays.asList(cmdLineArguments), CordaCapletTestUtils.getBaseDir()); + final File expected = Paths.get(".").resolve("node.conf").toAbsolutePath().normalize().toFile(); + assertEquals(expected, returnPath); + } +} + diff --git a/node/src/test/java/CordaCapletConfigFileParsingTest.java b/node/src/test/java/CordaCapletConfigFileParsingTest.java new file mode 100644 index 0000000000..48ddf1766d --- /dev/null +++ b/node/src/test/java/CordaCapletConfigFileParsingTest.java @@ -0,0 +1,40 @@ + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class CordaCapletConfigFileParsingTest { + @Parameterized.Parameters + public static Collection CombinationsToTest() { + return Arrays.asList( + new Object[][]{ + {new String[]{"--config-file", "blah.conf"}}, + {new String[]{"--config-file=blah.conf"}}, + {new String[]{"-f", "blah.conf"}}, + {new String[]{"-f=blah.conf"}} + }); + } + + private String[] cmdLineArguments; + + public CordaCapletConfigFileParsingTest(String[] arr) { + this.cmdLineArguments = arr; + } + + @Test + public void testThatConfigFileParameterIsRecognised() { + final CordaCaplet caplet = CordaCapletTestUtils.getCaplet(); + final File returnPath = caplet.getConfigFile(Arrays.asList(cmdLineArguments), CordaCapletTestUtils.getBaseDir()); + final File expected = Paths.get(".").resolve("blah.conf").toAbsolutePath().normalize().toFile(); + assertEquals(expected, returnPath.getAbsoluteFile()); + } +} + diff --git a/node/src/test/java/CordaCapletTestUtils.java b/node/src/test/java/CordaCapletTestUtils.java new file mode 100644 index 0000000000..cb282365dd --- /dev/null +++ b/node/src/test/java/CordaCapletTestUtils.java @@ -0,0 +1,16 @@ +import java.io.File; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Objects; + +class CordaCapletTestUtils { + static CordaCaplet getCaplet() { + final String path = System.getProperty("user.dir") + File.separator + "build" + File.separator + "libs" + File.separator; + final File jar = Arrays.stream(Objects.requireNonNull(new File(path).listFiles())).filter(x -> x.getName().startsWith("corda-node") && x.getName().endsWith(".jar")).findFirst().get(); + return new CordaCaplet(new Capsule(jar.toPath())); + } + + static String getBaseDir() { + return Paths.get(".").toAbsolutePath().normalize().toString(); + } +}