Created
April 26, 2015 12:34
-
-
Save lgoldstein/b88f50619cb5fd872304 to your computer and use it in GitHub Desktop.
OSV: Allow using a wrapper file to start JVM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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