/* $HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/webmoira/moirai.c $ $Id: moirai.c 3956 2010-01-05 20:56:56Z zacheiss $ */ #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_krb5_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); }