/** * Creates the Java library path. * -> where native shared libraries are searched * * It will consist of the following: * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/lib/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/common/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/common/lib/ */ static bool java_createNativeLibsPath(char* libraryPath, const size_t libraryPath_sizeMax) { // {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/ const char* const dd_r = callback->AIInterface_Info_getValueByKey(interfaceId, AI_INTERFACE_PROPERTY_DATA_DIR); if (dd_r == NULL) { simpleLog_logL(SIMPLELOG_LEVEL_ERROR, "Unable to find read-only data-dir."); return false; } else { STRCPYS(libraryPath, libraryPath_sizeMax, dd_r); } // {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/lib/ char* dd_lib_r = callback->DataDirs_allocatePath(interfaceId, NATIVE_LIBS_DIR, false, false, true, false); if (dd_lib_r == NULL) { simpleLog_logL(SIMPLELOG_LEVEL_NORMAL, "Unable to find read-only native libs data-dir (optional): %s", NATIVE_LIBS_DIR); } else { STRCATS(libraryPath, libraryPath_sizeMax, ENTRY_DELIM); STRCATS(libraryPath, libraryPath_sizeMax, dd_lib_r); FREE(dd_lib_r); } // {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/common/ const char* const dd_r_common = callback->AIInterface_Info_getValueByKey(interfaceId, AI_INTERFACE_PROPERTY_DATA_DIR_COMMON); if (dd_r_common == NULL || !util_fileExists(dd_r_common)) { simpleLog_logL(SIMPLELOG_LEVEL_NORMAL, "Unable to find common read-only data-dir (optional)."); } else { STRCATS(libraryPath, libraryPath_sizeMax, ENTRY_DELIM); STRCATS(libraryPath, libraryPath_sizeMax, dd_r_common); } // {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/common/lib/ if (dd_r_common != NULL) { char* dd_lib_r_common = callback->DataDirs_allocatePath(interfaceId, NATIVE_LIBS_DIR, false, false, true, true); if (dd_lib_r_common == NULL || !util_fileExists(dd_lib_r_common)) { simpleLog_logL(SIMPLELOG_LEVEL_NORMAL, "Unable to find common read-only native libs data-dir (optional)."); } else { STRCATS(libraryPath, libraryPath_sizeMax, ENTRY_DELIM); STRCATS(libraryPath, libraryPath_sizeMax, dd_lib_r_common); FREE(dd_lib_r_common); } } return true; }
bool GetJREPathFromBase(char* path, size_t pathSize, const char* basePath, const char* arch) { char jrePath[MAXPATHLEN]; bool found = false; if (basePath != NULL) { // Is basePath a JRE path? STRCPYS(jrePath, MAXPATHLEN, basePath); if (CheckIfJREPath(jrePath, arch)) { STRCPYS(path, pathSize, basePath); found = true; } // Is basePath/jre a JRE path? STRCATS(jrePath, MAXPATHLEN, "/jre"); if (CheckIfJREPath(jrePath, arch)) { STRCPYS(path, pathSize, jrePath); found = true; } } return found; }
static bool java_createJavaVMInitArgs(struct JavaVMInitArgs* vm_args, const struct Properties* jvmProps) { // ### evaluate JNI version to use ### //jint jniVersion = JNI_VERSION_1_1; //jint jniVersion = JNI_VERSION_1_2; jint jniVersion = JNI_VERSION_1_4; //jint jniVersion = JNI_VERSION_1_6; if (jvmProps != NULL) { const char* jniVersionFromCfg = java_getValueByKey(jvmProps, "jvm.jni.version"); if (jniVersionFromCfg != NULL) { unsigned long int jniVersion_tmp = strtoul(jniVersionFromCfg, NULL, 16); if (jniVersion_tmp != 0/* && jniVersion_tmp != ULONG_MAX*/) { jniVersion = (jint) jniVersion_tmp; } } } simpleLog_logL(SIMPLELOG_LEVEL_FINE, "JVM: JNI version: %#x", jniVersion); vm_args->version = jniVersion; // ### check if debug related JVM options should be used ### // if false, the JVM creation will fail if an // unknown or invalid option was specified bool useDebugOptions = true; const char* useDebugOptionsStr = "auto"; if (jvmProps != NULL) { const char* useDebugOptionsFromCfg = util_map_getValueByKey( jvmProps->size, jvmProps->keys, jvmProps->values, "jvm.useDebugOptions"); if (useDebugOptionsFromCfg != NULL) { useDebugOptionsStr = useDebugOptionsFromCfg; } } { if (strcmp(useDebugOptionsStr, "auto") == 0 || strcmp(useDebugOptionsStr, "Auto") == 0 || strcmp(useDebugOptionsStr, "AUTO") == 0 || strcmp(useDebugOptionsStr, "a") == 0 || strcmp(useDebugOptionsStr, "A") == 0) { // auto #if defined DEBUG useDebugOptions = true; #else // defined DEBUG useDebugOptions = false; #endif // defined DEBUG } else { // true or false useDebugOptions = util_strToBool(useDebugOptionsStr); } } // ### check if unrecognized JVM options should be ignored ### // if false, the JVM creation will fail if an // unknown or invalid option was specified bool ignoreUnrecognized = true; if (jvmProps != NULL) { const char* ignoreUnrecognizedFromCfg = java_getValueByKey(jvmProps, "jvm.arguments.ignoreUnrecognized"); if (ignoreUnrecognizedFromCfg != NULL && !util_strToBool(ignoreUnrecognizedFromCfg)) { ignoreUnrecognized = false; } } if (ignoreUnrecognized) { simpleLog_logL(SIMPLELOG_LEVEL_FINE, "JVM: ignoring unrecognized options"); vm_args->ignoreUnrecognized = JNI_TRUE; } else { simpleLog_logL(SIMPLELOG_LEVEL_FINE, "JVM: NOT ignoring unrecognized options"); vm_args->ignoreUnrecognized = JNI_FALSE; } // ### create the Java class-path option ### // autogenerate the class path static const size_t classPath_sizeMax = 8 * 1024; char* classPath = util_allocStr(classPath_sizeMax); // ..., autogenerate it ... if (!java_createClassPath(classPath, classPath_sizeMax)) { simpleLog_logL(SIMPLELOG_LEVEL_ERROR, "Failed creating Java class-path."); return false; } if (jvmProps != NULL) { // ..., and append the part from the jvm options properties file, // if it is specified there const char* clsPathFromCfg = java_getValueByKey(jvmProps, "jvm.option.java.class.path"); if (clsPathFromCfg != NULL) { STRCATS(classPath, classPath_sizeMax, ENTRY_DELIM); STRCATS(classPath, classPath_sizeMax, clsPathFromCfg); } } // create the java.class.path option static const size_t classPathOpt_sizeMax = 8 * 1024; char* classPathOpt = util_allocStr(classPathOpt_sizeMax); STRCPYS(classPathOpt, classPathOpt_sizeMax, "-Djava.class.path="); STRCATS(classPathOpt, classPathOpt_sizeMax, classPath); FREE(classPath); // ### create the Java library-path option ### // autogenerate the java library path static const size_t libraryPath_sizeMax = 4 * 1024; char* libraryPath = util_allocStr(libraryPath_sizeMax); // ..., autogenerate it ... if (!java_createNativeLibsPath(libraryPath, libraryPath_sizeMax)) { simpleLog_logL(SIMPLELOG_LEVEL_ERROR, "Failed creating Java library-path."); return false; } if (jvmProps != NULL) { // ..., and append the part from the jvm options properties file, // if it is specified there const char* libPathFromCfg = java_getValueByKey(jvmProps, "jvm.option.java.library.path"); if (libPathFromCfg != NULL) { STRCATS(libraryPath, libraryPath_sizeMax, ENTRY_DELIM); STRCATS(libraryPath, libraryPath_sizeMax, libPathFromCfg); } } // create the java.library.path option ... // autogenerate it, and append the part from the jvm options file, // if it is specified there static const size_t libraryPathOpt_sizeMax = 4 * 1024; char* libraryPathOpt = util_allocStr(libraryPathOpt_sizeMax); STRCPYS(libraryPathOpt, libraryPathOpt_sizeMax, "-Djava.library.path="); STRCATS(libraryPathOpt, libraryPathOpt_sizeMax, libraryPath); FREE(libraryPath); // ### create and set all JVM options ### static const size_t strOptions_sizeMax = 64; const char* strOptions[strOptions_sizeMax]; size_t op = 0; strOptions[op++] = classPathOpt; strOptions[op++] = libraryPathOpt; static const char* const JCPVAL = "-Djava.class.path="; const size_t JCPVAL_size = strlen(JCPVAL); static const char* const JLPVAL = "-Djava.library.path="; const size_t JLPVAL_size = strlen(JCPVAL); if (jvmProps != NULL) { // ### add string options from the JVM config file with property name "jvm.option.x" ### int i; for (i=0; i < jvmProps->size; ++i) { if (strcmp(jvmProps->keys[i], "jvm.option.x") == 0 || (useDebugOptions && (strcmp(jvmProps->keys[i], "jvm.option.debug.x") == 0))) { const char* const val = jvmProps->values[i]; const size_t val_size = strlen(val); // ignore "-Djava.class.path=..." // and "-Djava.library.path=..." options if (strncmp(val, JCPVAL, minSize(val_size, JCPVAL_size)) != 0 && strncmp(val, JLPVAL, minSize(val_size, JLPVAL_size)) != 0) { strOptions[op++] = val; } } } } else { // ### ... or set default ones, if the JVM config file was not found ### simpleLog_logL(SIMPLELOG_LEVEL_WARNING, "JVM: properties file ("JVM_PROPERTIES_FILE") not found; using default options."); strOptions[op++] = "-Xms4M"; strOptions[op++] = "-Xmx64M"; strOptions[op++] = "-Xss512K"; strOptions[op++] = "-Xoss400K"; #if defined DEBUG strOptions[op++] = "-Xcheck:jni"; strOptions[op++] = "-verbose:jni"; strOptions[op++] = "-XX:+UnlockDiagnosticVMOptions"; strOptions[op++] = "-XX:+LogVMOutput"; strOptions[op++] = "-Xdebug"; strOptions[op++] = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=7777"; // disable JIT (required for debugging under the classical VM) strOptions[op++] = "-Djava.compiler=NONE"; // disable old JDB strOptions[op++] = "-Xnoagent"; #endif // defined DEBUG } const size_t options_size = op; vm_args->options = (struct JavaVMOption*) calloc(options_size, sizeof(struct JavaVMOption)); // fill strOptions into the JVM options simpleLog_logL(SIMPLELOG_LEVEL_FINE, "JVM: options:", options_size); char* dd_rw = callback->DataDirs_allocatePath(interfaceId, "", true, true, true, false); size_t i; jint nOptions = 0; for (i = 0; i < options_size; ++i) { char* tmpOptionString = util_allocStrReplaceStr(strOptions[i], "${home-dir}", dd_rw); // do not add empty options if (tmpOptionString != NULL) { if (strlen(tmpOptionString) > 0) { vm_args->options[nOptions].optionString = tmpOptionString; vm_args->options[nOptions].extraInfo = NULL; simpleLog_logL(SIMPLELOG_LEVEL_FINE, "JVM option %ul: %s", nOptions, tmpOptionString); nOptions++; } else { free(tmpOptionString); tmpOptionString = NULL; } } } vm_args->nOptions = nOptions; FREE(dd_rw); FREE(classPathOpt); FREE(libraryPathOpt); simpleLog_logL(SIMPLELOG_LEVEL_FINE, ""); return true; }
/** * Creates the AI Interface global Java class path. * * It will consist of the following: * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/AIInterface.jar * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/(j)?config/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/(j)?config/[*].jar * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/(j)?resources/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/(j)?resources/[*].jar * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/(j)?script/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/(j)?script/[*].jar * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/jlib/ * {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/{version}/jlib/[*].jar * TODO: {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/common/jlib/ * TODO: {spring-data-dir}/{AI_INTERFACES_DATA_DIR}/Java/common/jlib/[*].jar */ static size_t java_createClassPath(char* classPathStr, const size_t classPathStr_sizeMax) { // the dirs and .jar files in the following array // will be concatenated with intermediate path separators // to form the classPathStr static const size_t classPath_sizeMax = 128; char** classPath = (char**) calloc(classPath_sizeMax, sizeof(char*)); size_t classPath_size = 0; // the Java AI Interfaces java library file path (.../AIInterface.jar) // We need to search for this jar, instead of looking only where // the AIInterface.so/InterfaceInfo.lua is, because on some systems // (eg. Debian), the .so is in /usr/lib, and the .jar's are in /usr/shared. char* mainJarPath = callback->DataDirs_allocatePath(interfaceId, JAVA_AI_INTERFACE_LIBRARY_FILE_NAME, false, false, false, false); classPath[classPath_size++] = util_allocStrCpy(mainJarPath); bool ok = util_getParentDir(mainJarPath); if (!ok) { simpleLog_logL(SIMPLELOG_LEVEL_ERROR, "Retrieving the parent dir of the path to AIInterface.jar (%s) failed.", mainJarPath); } char* jarsDataDir = mainJarPath; mainJarPath = NULL; // the directories in the following list will be searched for .jar files // which will then be added to the classPathStr, plus the dirs will be added // to the classPathStr directly, so you can keep .class files in there static const size_t jarDirs_sizeMax = 128; char** jarDirs = (char**) calloc(jarDirs_sizeMax, sizeof(char*)); size_t jarDirs_size = 0; // add to classpath: // {spring-data-dir}/Interfaces/Java/0.1/${x}/ jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "jconfig"); jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "config"); jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "jresources"); jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "resources"); jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "jscript"); jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "script"); jarDirs[jarDirs_size++] = util_allocStrCatFSPath(2, jarsDataDir, "jlib"); // "lib" is for native libs only // add the jar dirs (for .class files) and all contained .jars recursively size_t jd, jf; for (jd=0; (jd < jarDirs_size) && (classPath_size < classPath_sizeMax); ++jd) { if (util_fileExists(jarDirs[jd])) { // add the dir directly // For this to work properly with URLClassPathHandler, // we have to ensure there is a '/' at the end, // for the class-path-part to be recognized as a directory. classPath[classPath_size++] = util_allocStrCat(2, jarDirs[jd], "/"); // add the contained jars recursively static const size_t jarFiles_sizeMax = 128; char** jarFiles = (char**) calloc(jarFiles_sizeMax, sizeof(char*)); const size_t jarFiles_size = util_listFiles(jarDirs[jd], ".jar", jarFiles, true, jarFiles_sizeMax); for (jf=0; (jf < jarFiles_size) && (classPath_size < classPath_sizeMax); ++jf) { classPath[classPath_size++] = util_allocStrCatFSPath(2, jarDirs[jd], jarFiles[jf]); FREE(jarFiles[jf]); } FREE(jarFiles); } FREE(jarDirs[jd]); } FREE(jarDirs); // concat the classpath entries classPathStr[0] = '\0'; if (classPath[0] != NULL) { STRCATS(classPathStr, classPathStr_sizeMax, classPath[0]); FREE(classPath[0]); } size_t cp; for (cp=1; cp < classPath_size; ++cp) { if (classPath[cp] != NULL) { STRCATS(classPathStr, classPathStr_sizeMax, ENTRY_DELIM); STRCATS(classPathStr, classPathStr_sizeMax, classPath[cp]); FREE(classPath[cp]); } } FREE(classPath); return classPath_size; }