Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lgoldstein/b88f50619cb5fd872304 to your computer and use it in GitHub Desktop.
Save lgoldstein/b88f50619cb5fd872304 to your computer and use it in GitHub Desktop.
OSV: Allow using a wrapper file to start JVM
From 6c920c277f2e02d67a4f45241b080ed7b5ee446e Mon Sep 17 00:00:00 2001
From: Lyor Goldstein <lgoldstein@vmware.com>
Date: Sun, 26 Apr 2015 15:25:11 +0300
Subject: [PATCH] Allow using a wrapper file to start JVM
---
java/java.cc | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 194 insertions(+)
diff --git a/java/java.cc b/java/java.cc
index 8c14462..c094f39 100644
--- a/java/java.cc
+++ b/java/java.cc
@@ -94,6 +94,195 @@ static void on_vm_stop(JNIEnv *env, jclass clz) {
attached_env::set_jvm(nullptr);
}
+inline bool is_whitespace(char c) {
+ if ((c == ' ') || (c == '\t')) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static char *trim(char *s) {
+ size_t startPos=0, maxPos=strlen(s), endPos=maxPos;
+ for ( ; startPos < endPos; startPos++) {
+ char c=s[startPos];
+ if (!is_whitespace(c)) {
+ break;
+ }
+ }
+
+ for ( ; endPos > startPos; endPos--) {
+ char c=s[endPos - 1];
+ if (!is_whitespace(c)) {
+ break;
+ }
+ }
+
+ if ((startPos == 0) && (endPos == maxPos)) {
+ return s;
+ }
+
+ // check if trimmed any characters at end of string
+ if (endPos < maxPos) {
+ s[endPos] = '\0';
+ }
+
+ // check if trimmed any characters at start of string
+ if (startPos > 0) {
+ size_t curPos=0;
+ for ( ; startPos < endPos; startPos++, curPos++) {
+ s[curPos] = s[startPos];
+ }
+ s[curPos] = '\0';
+ }
+
+ return s;
+}
+
+static int get_values_list(std::map<std::string,std::string> &configMap, const char *prefix, std::vector<std::string> &out) {
+ int index=1;
+ for ( ; ; index++) {
+ std::string key(prefix);
+ key += std::string(".");
+ key += std::to_string(index);
+
+ std::map<std::string,std::string>::iterator it=configMap.find(key);
+ if (it == configMap.end()) {
+ break;
+ }
+
+ std::string value=it->second;
+
+ // TODO check if need to strip quotes
+#if 0
+ key += std::string(".stripquotes");
+ if ((it=configMap.find(key)) != configMap.end()) {
+ const char *s=value.c_str();
+ ...strip quotes and replace value ...
+ }
+#endif
+
+ out.push_back(value);
+ }
+
+ return index - 1;
+}
+
+static char *duplicate_wrapper_value(const std::string& str) {
+ const char *s=str.c_str();
+ return strdup(s);
+}
+
+static int duplicate_wrapper_values(std::vector<std::string>& values, char **argv, int startPos, int numValues) {
+ int curPos=startPos, index=0;
+ for (index=0; index < numValues; index++, curPos++) {
+ argv[curPos] = duplicate_wrapper_value(values[index]);
+ }
+
+ return curPos;
+}
+
+static int process_wrapper_configuration(std::map<std::string,std::string> &configMap, int& argc, char **&argv) {
+ std::map<std::string,std::string>::iterator it=configMap.find(std::string("wrapper.java.mainclass"));
+ if (it == configMap.end()) {
+ std::cerr << "java.so: Missing main class specification in wrapper configuration.\n";
+ return 1;
+ }
+
+ std::string mainClass=it->second;
+ std::vector<std::string> jvmDefs, appParams, classpath;
+ int numJvmDefs=get_values_list(configMap, "wrapper.java.additional", jvmDefs);
+ int numClasspath=get_values_list(configMap, "wrapper.java.classpath", classpath);
+ int numAppParams=get_values_list(configMap, "wrapper.app.parameter", appParams);
+ int totalParams=1 /* argv[0] */ + ((numClasspath > 0) ? 2 /* -cp + path */ : 0) + numJvmDefs + 1 /* main class */ + numAppParams + 1 /* last is NULL */;
+ char **replArgv=(char **) malloc(totalParams * sizeof(char *));
+ replArgv[0] = argv[0]; // argv[0] is the same as the original
+
+ int curPos=duplicate_wrapper_values(jvmDefs, replArgv, 1, numJvmDefs);
+ if (numClasspath > 0) {
+ std::string joined;
+ for (int index=0; index < numClasspath; index++) {
+ std::string path=classpath[index];
+ if (joined.length() > 0) {
+ joined += std::string(":"); // NOTE: we use the Linux path separator as OSV is Linux-like
+ }
+
+ joined += path;
+ }
+
+ replArgv[curPos] = strdup("-cp");
+ curPos++;
+ replArgv[curPos] = duplicate_wrapper_value(joined);
+ curPos++;
+ }
+
+ replArgv[curPos] = duplicate_wrapper_value(mainClass);
+ curPos++;
+ curPos = duplicate_wrapper_values(appParams, replArgv, curPos, numAppParams);
+ replArgv[curPos] = NULL; // mark end
+
+ argv = replArgv;
+ argc = curPos;
+ return 0;
+}
+
+#define MAX_WRAPPER_LINE_LENGTH 1024
+static int read_wrapper_configuration_file(FILE *fp, int& argc, char **&argv) {
+ char line[MAX_WRAPPER_LINE_LENGTH + sizeof(int)], *sep;
+ int lineNumber=1;
+ std::map<std::string,std::string> configMap;
+
+ for (lineNumber=1; fgets(line, MAX_WRAPPER_LINE_LENGTH, fp) != NULL; lineNumber++) {
+ line[MAX_WRAPPER_LINE_LENGTH] = '\0'; // just make sure
+ trim(line);
+
+ // skip empty and/or comment lines
+ if ((line[0] == '\0') || (line[0] == '#')) {
+ continue;
+ }
+
+ // allow both separators
+ sep = strchr(line, '=');
+ if (sep == NULL) {
+ sep = strchr(line, ':');
+ }
+
+ if (sep == NULL) {
+ std::cerr << "java.so: Missing name/value separator at line #" << lineNumber << " of wrapper configuration.\n";
+ return 1;
+ }
+
+ *sep = '\0'; // create 2 strings
+
+ std::string name(line), value(trim(sep + 1));
+ configMap[name] = value;
+ }
+
+ return process_wrapper_configuration(configMap, argc, argv);
+}
+
+static int read_wrapper_configuration(const char *path, int& argc, char **&argv) {
+ FILE *fp=fopen(path, "r");
+ if (fp == NULL) {
+ std::cerr << "java.so: Can't open " << path << " to read wrapper configuration.\n";
+ return 1;
+ }
+
+ int err=read_wrapper_configuration_file(fp, argc, argv);
+ fclose(fp);
+ return err;
+}
+
+// Based on the http://wrapper.tanukisoftware.com/doc/english/properties.html#name
+static int check_wrapper(int& argc, char **&argv) {
+ // if using the wrapper option then it must be the ONLY one and have EXACTLY one "argument" - the configuration file
+ if ((argc != 3) || (strcmp(argv[1], "--wrapper") != 0)) {
+ return 0;
+ } else {
+ return read_wrapper_configuration(argv[2], argc, argv);
+ }
+}
+
static int java_main(int argc, char **argv)
{
auto prog = elf::get_program();
@@ -131,6 +320,11 @@ static int java_main(int argc, char **argv)
}
}
+ int err=check_wrapper(argc, argv);
+ if (err != 0) {
+ return err;
+ }
+
int orig_argc = argc;
int has_xms = 0, has_xmx = 0;
--
1.9.5.msysgit.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment