Skip to content

Commit

Permalink
CORDA-736 Add some new features to corda.jar via node.conf for testing (
Browse files Browse the repository at this point in the history
  • Loading branch information
rick-r3 authored Oct 24, 2017
1 parent 9279244 commit 4b8590e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 14 deletions.
10 changes: 10 additions & 0 deletions docs/source/corda-configuration-file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,13 @@ path to the node's base directory.

:certificateSigningService: Certificate Signing Server address. It is used by the certificate signing request utility to
obtain SSL certificate. (See :doc:`permissioning` for more information.)

:jvmArgs: An optional list of JVM args, as strings, which replace those inherited from the command line when launching via ``corda.jar``
only. e.g. ``jvmArgs = [ "-Xmx220m", "-Xms220m", "-XX:+UseG1GC" ]``

:systemProperties: An optional map of additional system properties to be set when launching via ``corda.jar`` only. Keys and values
of the map should be strings. e.g. ``systemProperties = { visualvm.display.name = FooBar }``

:jarDirs: An optional list of file system directories containing JARs to include in the classpath when launching via ``corda.jar`` only.
Each should be a string. Only the JARs in the directories are added, not the directories themselves. This is useful
for including JDBC drivers and the like. e.g. ``jarDirs = [ 'lib' ]``
6 changes: 5 additions & 1 deletion node/capsule/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ task buildCordaJAR(type: FatCapsule, dependsOn: project(':node').compileJava) {
"$rootDir/config/dev/log4j2.xml"
)
from 'NOTICE' // Copy CDDL notice

from { project(':node').configurations.runtime.allDependencies.matching { // Include config library JAR.
it.group.equals("com.typesafe") && it.name.equals("config")
}.collect { zipTree(project(':node').configurations.runtime.files(it).first()) } }
from { "$rootDir/node/build/resources/main/reference.conf" }

capsuleManifest {
applicationVersion = corda_release_version
Expand All @@ -47,6 +50,7 @@ task buildCordaJAR(type: FatCapsule, dependsOn: project(':node').compileJava) {
// JVM configuration:
// - Constrain to small heap sizes to ease development on low end devices.
// - Switch to the G1 GC which is going to be the default in Java 9 and gives low pause times/string dedup.
// NOTE: these can be overridden in node.conf.
//
// If you change these flags, please also update Driver.kt
jvmArgs = ['-Xmx200m', '-XX:+UseG1GC']
Expand Down
116 changes: 104 additions & 12 deletions node/src/main/java/CordaCaplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,73 @@
// must also be in the default package. When using Kotlin there are a whole host of exceptions
// trying to construct this from Capsule, so it is written in Java.

import sun.misc.*;
import com.typesafe.config.*;
import sun.misc.Signal;
import sun.misc.SignalHandler;

import java.io.*;
import java.nio.file.*;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

public class CordaCaplet extends Capsule {

private Config nodeConfig = null;
private String baseDir = null;

protected CordaCaplet(Capsule pred) {
super(pred);
}

private Config parseConfigFile(List<String> args) {
String baseDirOption = getOption(args, "--base-directory");
this.baseDir = Paths.get((baseDirOption == null) ? "." : baseDirOption).toAbsolutePath().normalize().toString();
String config = getOption(args, "--config-file");
File configFile = (config == null) ? new File(baseDir, "node.conf") : new File(config);
try {
ConfigParseOptions parseOptions = ConfigParseOptions.defaults().setAllowMissing(false);
Config defaultConfig = ConfigFactory.parseResources("reference.conf", parseOptions);
Config baseDirectoryConfig = ConfigFactory.parseMap(Collections.singletonMap("baseDirectory", baseDir));
Config nodeConfig = ConfigFactory.parseFile(configFile, parseOptions);
return baseDirectoryConfig.withFallback(nodeConfig).withFallback(defaultConfig).resolve();
} catch (ConfigException e) {
log(LOG_QUIET, e);
return ConfigFactory.empty();
}
}

private String getOption(List<String> 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) {
return args.get(index + 1);
} else {
return null;
}
}
index++;
}
return null;
}

@Override
protected ProcessBuilder prelaunch(List<String> jvmArgs, List<String> args) {
nodeConfig = parseConfigFile(args);
return super.prelaunch(jvmArgs, args);
}

// Add working directory variable to capsules string replacement variables.
@Override
protected String getVarValue(String var) {
if (var.equals("baseDirectory")) {
return baseDir;
} else {
return super.getVarValue(var);
}
}

/**
* Overriding the Caplet classpath generation via the intended interface in Capsule.
*/
Expand All @@ -25,18 +80,55 @@ protected <T> T attribute(Map.Entry<String, T> attr) {
if (ATTR_APP_CLASS_PATH == attr) {
T cp = super.attribute(attr);

(new File("cordapps")).mkdir();
augmentClasspath((List<Path>) cp, "cordapps");
augmentClasspath((List<Path>) cp, "plugins");
(new File(baseDir, "cordapps")).mkdir();
augmentClasspath((List<Path>) cp, new File(baseDir, "cordapps"));
augmentClasspath((List<Path>) cp, new File(baseDir, "plugins"));
// Add additional directories of JARs to the classpath (at the end). e.g. for JDBC drivers
try {
List<String> jarDirs = nodeConfig.getStringList("jarDirs");
log(LOG_VERBOSE, "Configured JAR directories = " + jarDirs);
for (String jarDir : jarDirs) {
augmentClasspath((List<Path>) cp, new File(jarDir));
}
} catch (ConfigException.Missing e) {
// Ignore since it's ok to be Missing. Other errors would be unexpected.
} catch (ConfigException e) {
log(LOG_QUIET, e);
}
return cp;
}
return super.attribute(attr);
} else if (ATTR_JVM_ARGS == attr) {
// Read JVM args from the config if specified, else leave alone.
List<String> jvmArgs = new ArrayList<>((List<String>) super.attribute(attr));
try {
List<String> configJvmArgs = nodeConfig.getStringList("jvmArgs");
jvmArgs.clear();
jvmArgs.addAll(configJvmArgs);
log(LOG_VERBOSE, "Configured JVM args = " + jvmArgs);
} catch (ConfigException.Missing e) {
// Ignore since it's ok to be Missing. Other errors would be unexpected.
} catch (ConfigException e) {
log(LOG_QUIET, e);
}
return (T) jvmArgs;
} else if (ATTR_SYSTEM_PROPERTIES == attr) {
// Add system properties, if specified, from the config.
Map<String, String> systemProps = new LinkedHashMap<>((Map<String, String>) super.attribute(attr));
try {
Config overrideSystemProps = nodeConfig.getConfig("systemProperties");
log(LOG_VERBOSE, "Configured system properties = " + overrideSystemProps);
for (Map.Entry<String, ConfigValue> entry : overrideSystemProps.entrySet()) {
systemProps.put(entry.getKey(), entry.getValue().unwrapped().toString());
}
} catch (ConfigException.Missing e) {
// Ignore since it's ok to be Missing. Other errors would be unexpected.
} catch (ConfigException e) {
log(LOG_QUIET, e);
}
return (T) systemProps;
} else return super.attribute(attr);
}

// TODO: Make directory configurable via the capsule manifest.
// TODO: Add working directory variable to capsules string replacement variables.
private void augmentClasspath(List<Path> classpath, String dirName) {
File dir = new File(dirName);
private void augmentClasspath(List<Path> classpath, File dir) {
if (dir.exists()) {
File[] files = dir.listFiles();
for (File file : files) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,10 @@ class NodeProcess(

private fun startNode(nodeDir: Path): Process {
val builder = ProcessBuilder()
.command(javaPath.toString(), "-jar", cordaJar.toString())
.command(javaPath.toString(), "-Dcapsule.log=verbose", "-jar", cordaJar.toString())
.directory(nodeDir.toFile())
.redirectError(ProcessBuilder.Redirect.INHERIT)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)

builder.environment().putAll(mapOf(
"CAPSULE_CACHE_DIR" to (buildDirectory / "capsule").toString()
Expand Down

0 comments on commit 4b8590e

Please sign in to comment.