X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/7674bbe4e4021d3214cd6ac45c807123547d5d66..bde1652c9c4187fb2f212baf2f35696e81d0c08a:/webmoira/moirai.c diff --git a/webmoira/moirai.c b/webmoira/moirai.c new file mode 100644 index 00000000..31c0c3e5 --- /dev/null +++ b/webmoira/moirai.c @@ -0,0 +1,298 @@ +#include "mit_moira_MoiraConnectInternal.h" +#include +#include +#include +#include +#include + +static void throwMoiraException(JNIEnv *env, int code) +{ + char buffer[1024]; + jmethodID mid; + jobject tothrow; + jclass IOE; + jstring jmess; + + IOE = (*env)->FindClass(env, "mit/moira/MoiraException"); + if (IOE == NULL) { + fprintf(stderr, "moirai: No Class\n"); + goto die; + } + mid = (*env)->GetMethodID(env, IOE, "", "(Ljava/lang/String;I)V"); + if (mid == NULL) { + fprintf(stderr, "moirai: No Method\n"); + goto die; + } + sprintf(buffer, "%s", error_message(code)); + jmess = (*env)->NewStringUTF(env, buffer); + if (jmess == NULL) { + fprintf(stderr, "Cannot get new string\n"); + goto die; + } + tothrow = (*env)->NewObject(env, IOE, mid, jmess, (jint) code); + if (tothrow == NULL) { + fprintf(stderr, "moirai: No Throw\n"); + goto die; + } + (*env)->Throw(env, (jthrowable) tothrow); + return; + die: + abort(); + return; +} + +static void throwMoiraExceptionMess(JNIEnv *env, char *mess) +{ + jclass IOE = (*env)->FindClass(env, "mit/moira/MoiraException"); + if (IOE == NULL) abort(); + (*env)->ThrowNew(env, IOE, mess); + return; +} + +JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_connect(JNIEnv *env, + jclass Class, jstring server) { + int status; + char buffer[1024]; + const char *aserver = (*env)->GetStringUTFChars(env, server, 0); + if (strlen(aserver) > sizeof(buffer)) abort(); + strcpy(buffer, aserver); + (*env)->ReleaseStringUTFChars(env, server, aserver); + status = mr_connect(buffer); + if (status != MR_SUCCESS) throwMoiraException(env, status); + status = mr_version(2); + if (status != MR_SUCCESS) { + if (status == MR_VERSION_LOW) return; /* This is OK */ + else { + mr_disconnect(); + throwMoiraException(env, status); + } + } + return; +} + +JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_proxy(JNIEnv *env, + jclass Class, + jstring jUser) { + int status; + char buffer[1024]; + const char *user = (*env)->GetStringUTFChars(env, jUser, 0); + if (strlen(user) > sizeof(buffer)) abort(); + strcpy(buffer, user); + (*env)->ReleaseStringUTFChars(env, jUser, user); + status = mr_proxy(buffer, "Java"); + if (status != MR_SUCCESS) throwMoiraException(env, status); + return; +} + + +JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_auth(JNIEnv *env, + jclass Class) { + int status; + status = mr_auth("JavaInterface"); + if (status != MR_SUCCESS) throwMoiraException(env, status); + return; +} + +JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_disconnect + (JNIEnv *env, jclass Class) { + mr_disconnect(); + return; +} + +typedef struct ArgBlock { + int alloccount; + int count; + char **stringval; +} ArgBlock; + +typedef struct ListBlock { + int alloccount; + int count; + ArgBlock **Args; +} ListBlock; + +static jobjectArray ArgBlockToJavaArray(JNIEnv *env, ArgBlock *argb); +static jobjectArray ListBlockToJavaArray(JNIEnv *env, ListBlock *lb); + +extern int mr_query(char *name, int argc, char **argv, + int (*proc)(int, char **, void *), void *hint); +static ListBlock *NewListBlock(); +static ArgBlock *NewArgBlock(); +static void FreeListBlock(ListBlock *); +static int StashResults(int argc, char **argv, void *callback); +static char **ConvertJavaArgs(JNIEnv *env, jobjectArray jargs); +static void FreeArgs(char **args); + +JNIEXPORT jobjectArray JNICALL Java_mit_moira_MoiraConnectInternal_mr_1query + (JNIEnv *env, jclass Class, jstring jcommand, jobjectArray jargs) { + ListBlock *listblock = NewListBlock(); + jobjectArray retval; + int status; + const char *command; + char icommand[1024]; + char **args = ConvertJavaArgs(env, jargs); + if (args == NULL) return (NULL); /* It probably thru an exception */ + command = (*env)->GetStringUTFChars(env, jcommand, 0); + strncpy(icommand, command, sizeof(icommand)); + + status = mr_query(icommand, (*env)->GetArrayLength(env, jargs), args, + StashResults, listblock); + FreeArgs(args); /* Don't need them anymore */ + if (status != MR_SUCCESS) { + FreeListBlock(listblock); + throwMoiraException(env, status); + return (0); + } + /* if (listblock->count == 0) { / * No such list or empty list * / + FreeListBlock(listblock); + throwMoiraExceptionMess(env, "No Such List or Empty List"); + return(0); + } */ + + if (listblock->count == 0) return (0); + + retval = ListBlockToJavaArray(env, listblock); + FreeListBlock(listblock); + return (retval); + +} + +static ArgBlock *NewArgBlock() { + ArgBlock *argb = (ArgBlock *)malloc(sizeof(ArgBlock)); + argb->alloccount = 10; + argb->stringval = (char **) malloc(10 * sizeof(char *)); + argb->count = 0; + return (argb); +} + +static void AddArg(ArgBlock *argb, char *arg) { + int i; + if (argb->alloccount <= (argb->count + 1)) { + char **st = malloc((2 * argb->alloccount) * sizeof(char *)); + argb->alloccount *= 2; + for (i = 0; i < argb->count; i++) + st[i] = argb->stringval[i]; + free(argb->stringval); + argb->stringval = st; + } + argb->stringval[argb->count++] = arg; +} + +static ListBlock *NewListBlock() { + ListBlock *list = (ListBlock *)malloc(sizeof(ListBlock)); + list->alloccount = 10; + list->Args = (ArgBlock **) malloc(10 * sizeof(ArgBlock *)); + list->count = 0; + return (list); +} + +static void FreeArgBlock(ArgBlock *argb) { + int i; + for (i = 0; i < argb->count; i++) free(argb->stringval[i]); + free(argb->stringval); + free(argb); +} + +static void FreeListBlock(ListBlock *list) { + int i; + for (i = 0; i < list->count; i++) FreeArgBlock(list->Args[i]); + free(list->Args); + free(list); +} + +static jobjectArray ArgBlockToJavaArray(JNIEnv *env, ArgBlock *argb) { + jobjectArray retval; + int i; + retval = (*env)->NewObjectArray(env, argb->count, + (*env)->FindClass(env, "java/lang/String"), + NULL); + for (i = 0; i < argb->count; i++) { + (*env)->SetObjectArrayElement(env, retval, i, + (*env)->NewStringUTF(env, argb->stringval[i])); + } + return (retval); +} + +static jobjectArray ListBlockToJavaArray(JNIEnv *env, ListBlock *lb) { + jobjectArray retval; + int i; + retval = (*env)->NewObjectArray(env, lb->count, + (*env)->FindClass(env, "java/lang/Object"), + NULL); + for (i = 0; i < lb->count; i++) + (*env)->SetObjectArrayElement(env, retval, i, + ArgBlockToJavaArray(env, lb->Args[i])); + return (retval); +} + +static int StashResults(int argc, char **argv, void *callback) { + ListBlock *list = (ListBlock *) callback; + ArgBlock *argb; + char *arg; + int i; + + /* printf("DEBUG: StashResults argc = %d\n", argc); + * for (i = 0; i < argc; i++) + * printf("DEBUG: StashResults argv[%d] = %s\n", i, argv[i]); + */ + + while (list->alloccount <= (list->count + 1)) { + ArgBlock **args = (ArgBlock **) malloc(list->alloccount * 2 * sizeof(char *)); + list->alloccount = list->alloccount * 2; + for(i = 0; i < list->count; i++) { + args[i] = list->Args[i]; + } + free(list->Args); + list->Args = args; + } + + argb = NewArgBlock(); + + for (i = 0; i < argc; i++) { + arg = (char *) malloc(strlen(argv[i]) + 1); + strcpy(arg, argv[i]); + AddArg(argb, arg); + } + list->Args[list->count++] = argb; + return (0); +} + +static char **ConvertJavaArgs(JNIEnv *env, jobjectArray jargs) { + char **retval; + int i, j; + const char *iarg; + int length = (*env)->GetArrayLength(env, jargs); + if (length == 0) { /* Does this happen in a non-error situation? */ + retval = (char **) malloc(sizeof (char *)); + retval[0] = NULL; + return(retval); + } + retval = (char **) malloc((length + 1) * sizeof(char *)); + for (i = 0; i < length; i++) { + jobject jarg = (*env)->GetObjectArrayElement(env, jargs, i); + if ((*env)->ExceptionOccurred(env)) { + for (j = 0; j < i; j++) free(retval[j]); + free (retval); + return (NULL); + } + iarg = (*env)->GetStringUTFChars(env, jarg, 0); + if ((*env)->ExceptionOccurred(env)) { + for (j = 0; j < i; j++) free(retval[j]); + free (retval); + return (NULL); + } + retval[i] = malloc(strlen(iarg) + 1); + strcpy(retval[i], iarg); + (*env)->ReleaseStringUTFChars(env, jarg, iarg); + } + retval[length] = NULL; + return (retval); +} + +static void FreeArgs(char **args) { + int i; + i = 0; + while (args[i] != NULL) free(args[i++]); + free(args); +} +