Goto sanos source index
//
// jinit.h
//
// Java VM launcher
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <os.h>
#include <java/jni.h>
#include <string.h>
#include <inifile.h>
#include <stdlib.h>
struct section *cfg;
char *cfgname;
JavaVM *vm = NULL;
JNIEnv *env = NULL;
JavaVMInitArgs args;
hmodule_t hjvm;
jint (JNICALL *CreateJavaVM)(JavaVM **pvm, void **env, void *args);
jclass load_class(JNIEnv *env, char *name)
{
jclass cls;
char clsname[128];
char *s;
char *t;
s = name;
t = clsname;
while (*s)
{
*t++ = *s == '.' ? '/' : *s;
s++;
}
*t = 0;
cls = (*env)->FindClass(env, clsname);
return cls;
}
jstring new_string(JNIEnv *env, char *s)
{
int len = strlen(s);
jclass cls;
jmethodID mid;
jbyteArray ary;
cls = (*env)->FindClass(env, "java/lang/String");
mid = (*env)->GetMethodID(env, cls, "<init>", "([B)V");
ary = (*env)->NewByteArray(env, len);
if (ary != 0)
{
jstring str = 0;
(*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *) s);
if (!(*env)->ExceptionOccurred(env))
{
str = (*env)->NewObject(env, cls, mid, ary);
}
(*env)->DeleteLocalRef(env, ary);
return str;
}
return 0;
}
jobjectArray new_string_array(JNIEnv *env, int strc, char **strv)
{
jarray cls;
jarray ary;
int i;
cls = (*env)->FindClass(env, "java/lang/String");
ary = (*env)->NewObjectArray(env, strc, cls, 0);
for (i = 0; i < strc; i++)
{
jstring str = new_string(env, *strv++);
(*env)->SetObjectArrayElement(env, ary, i, str);
(*env)->DeleteLocalRef(env, str);
}
return ary;
}
void init_jvm_args()
{
JavaVMOption *options;
struct section *optsect;
struct section *propsect;
struct section *cpsect;
int nopts;
int n;
struct property *prop;
char *buf;
char *p;
int len;
int first;
cpsect = find_section(cfg, get_property(cfg, cfgname, "classpaths", "java.classpaths"));
optsect = find_section(cfg, get_property(cfg, cfgname, "options", "java.options"));
propsect = find_section(cfg, get_property(cfg, cfgname, "properties", "java.properties"));
nopts = get_section_size(optsect) + get_section_size(propsect) + (cpsect ? 1 : 0);
options = (JavaVMOption *) malloc(nopts * sizeof(JavaVMOption));
memset(options, 0, nopts * sizeof(JavaVMOption));
n = 0;
if (cpsect)
{
len = strlen("-Djava.class.path=") + 1;
prop = cpsect->properties;
while (prop)
{
if (prop->name) len += strlen(prop->name) + 1;
if (prop->value) len += strlen(prop->value) + 1;
prop = prop->next;
}
buf = (char *) malloc(len);
strcpy(buf, "-Djava.class.path=");
p = buf + strlen(buf);
first = 1;
prop = cpsect->properties;
while (prop)
{
if (!first) *p++ = ';';
first = 0;
if (prop->name)
{
len = strlen(prop->name);
memcpy(p, prop->name, len + 1);
p += len;
}
if (prop->value)
{
*p++ = ':';
len = strlen(prop->value);
memcpy(p, prop->value, len + 1);
p += len;
}
prop = prop->next;
}
options[n++].optionString = buf;
}
if (optsect)
{
prop = optsect->properties;
while (prop)
{
if (prop->value)
{
len = strlen(prop->name) + 1 + strlen(prop->value);
buf = (char *) malloc(len + 1);
strcpy(buf, prop->name);
strcpy(buf + strlen(buf), ":");
strcpy(buf + strlen(buf), prop->value);
}
else
{
len = strlen(prop->name);
buf = (char *) malloc(len + 1);
strcpy(buf, prop->name);
}
options[n++].optionString = buf;
prop = prop->next;
}
}
if (propsect)
{
prop = propsect->properties;
while (prop)
{
if (prop->value)
len = 2 + strlen(prop->name) + 1 + strlen(prop->value);
else
len = 2 + strlen(prop->name);
buf = (char *) malloc(len + 1);
strcpy(buf, "-D");
strcpy(buf + strlen(buf), prop->name);
if (prop->value)
{
strcpy(buf + strlen(buf), "=");
strcpy(buf + strlen(buf), prop->value);
}
options[n++].optionString = buf;
prop = prop->next;
}
}
memset(&args, 0, sizeof(args));
args.version = JNI_VERSION_1_2;
args.nOptions = nopts;
args.options = options;
args.ignoreUnrecognized = JNI_FALSE;
}
int init_jvm()
{
jint rc;
// Get JVM options from os.ini
init_jvm_args();
// Load VM
if (hjvm == NULL)
{
char *jvmname = get_property(cfg, cfgname, "jvm", "jvm.dll");
hjvm = dlopen(jvmname, 0);
if (hjvm == NULL)
{
syslog(LOG_ERR, "Error loading JVM %s", jvmname);
return -1;
}
}
if (!CreateJavaVM)
{
CreateJavaVM = (jint (JNICALL *)(JavaVM **pvm, void **env, void *args)) dlsym(hjvm, "JNI_CreateJavaVM");
if (!CreateJavaVM)
{
syslog(LOG_ERR, "Unable to find CreateJavaVM");
return -1;
}
}
// Create VM instance
if (!vm)
{
rc = CreateJavaVM(&vm, (void **) &env, &args);
if (rc != JNI_OK)
{
syslog(LOG_ERR, "Error %d creating java vm", rc);
return -1;
}
}
else
{
rc = (*vm)->AttachCurrentThread(vm, (void **) &env, &args);
if (rc != JNI_OK)
{
syslog(LOG_ERR, "Error %d attaching to vm", rc);
return -1;
}
}
return 0;
}
int execute_main_method(char *mainclsname, char *mainclsargs)
{
int argc;
char **argv;
jclass mainclass;
jmethodID mainid;
jobjectArray mainargs;
// Load main class
mainclass = load_class(env, mainclsname);
if (mainclass == NULL)
{
syslog(LOG_ERR, "Unable to find main class %s", mainclsname);
return -1;
}
// Find main method
mainid = (*env)->GetStaticMethodID(env, mainclass, "main", "([Ljava/lang/String;)V");
if (mainid == NULL)
{
syslog(LOG_ERR, "Class %s does not have a main method", mainclsname);
return -1;
}
// Create argument array
argc = parse_args(mainclsargs, NULL);
if (argc)
{
argv = (char **) malloc(argc * sizeof(char *));
parse_args(mainclsargs, argv);
}
else
argv = NULL;
mainargs = new_string_array(env, argc, argv);
if (mainargs == NULL)
{
syslog(LOG_ERR, "Error creating command arguments");
return -1;
}
// Invoke main method
(*env)->CallStaticVoidMethod(env, mainclass, mainid, mainargs);
if ((*env)->ExceptionOccurred(env))
{
(*env)->ExceptionDescribe(env);
return -1;
}
free_args(argc, argv);
return 0;
}
int main(int argc, char *argv[])
{
char *mainclsname;
char *mainclsargs;
// Determine configuration
if (argc > 1)
cfgname = argv[1];
else
cfgname = "java";
if (argc > 2)
{
cfg = read_properties(argv[2]);
if (cfg == NULL)
{
syslog(LOG_ERR, "Unable to read JVM configuration from %s", argv[2]);
return 1;
}
}
else
cfg = osconfig();
// Initialize Java VM
if (init_jvm() != 0) return 1;
// Get main class and arguments
mainclsname = get_property(cfg, cfgname, "mainclass", "sanos.os.Shell");
mainclsargs = get_property(cfg, cfgname, "mainargs", "");
// Call main method
execute_main_method(mainclsname, mainclsargs);
// Detach main thread from jvm
if ((*vm)->DetachCurrentThread(vm) != 0)
{
syslog(LOG_ERR, "Could not detach main thread");
return 1;
}
(*vm)->DestroyJavaVM(vm);
return 0;
}