[24319] | 1 | /* $HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/webmoira/moirai.c $ $Id: moirai.c 3956 2010-01-05 20:56:56Z zacheiss $ */ |
---|
[23095] | 2 | #include "mit_moira_MoiraConnectInternal.h" |
---|
| 3 | #include <moira.h> |
---|
| 4 | #include <mr_et.h> |
---|
| 5 | #include <malloc.h> |
---|
| 6 | #include <string.h> |
---|
| 7 | #include <stdio.h> |
---|
| 8 | |
---|
| 9 | static void throwMoiraException(JNIEnv *env, int code) |
---|
| 10 | { |
---|
| 11 | char buffer[1024]; |
---|
| 12 | jmethodID mid; |
---|
| 13 | jobject tothrow; |
---|
| 14 | jclass IOE; |
---|
| 15 | jstring jmess; |
---|
| 16 | |
---|
| 17 | IOE = (*env)->FindClass(env, "mit/moira/MoiraException"); |
---|
| 18 | if (IOE == NULL) { |
---|
| 19 | fprintf(stderr, "moirai: No Class\n"); |
---|
| 20 | goto die; |
---|
| 21 | } |
---|
| 22 | mid = (*env)->GetMethodID(env, IOE, "<init>", "(Ljava/lang/String;I)V"); |
---|
| 23 | if (mid == NULL) { |
---|
| 24 | fprintf(stderr, "moirai: No Method\n"); |
---|
| 25 | goto die; |
---|
| 26 | } |
---|
| 27 | sprintf(buffer, "%s", error_message(code)); |
---|
| 28 | jmess = (*env)->NewStringUTF(env, buffer); |
---|
| 29 | if (jmess == NULL) { |
---|
| 30 | fprintf(stderr, "Cannot get new string\n"); |
---|
| 31 | goto die; |
---|
| 32 | } |
---|
| 33 | tothrow = (*env)->NewObject(env, IOE, mid, jmess, (jint) code); |
---|
| 34 | if (tothrow == NULL) { |
---|
| 35 | fprintf(stderr, "moirai: No Throw\n"); |
---|
| 36 | goto die; |
---|
| 37 | } |
---|
| 38 | (*env)->Throw(env, (jthrowable) tothrow); |
---|
| 39 | return; |
---|
| 40 | die: |
---|
| 41 | abort(); |
---|
| 42 | return; |
---|
| 43 | } |
---|
| 44 | |
---|
| 45 | static void throwMoiraExceptionMess(JNIEnv *env, char *mess) |
---|
| 46 | { |
---|
| 47 | jclass IOE = (*env)->FindClass(env, "mit/moira/MoiraException"); |
---|
| 48 | if (IOE == NULL) abort(); |
---|
| 49 | (*env)->ThrowNew(env, IOE, mess); |
---|
| 50 | return; |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_connect(JNIEnv *env, |
---|
| 54 | jclass Class, jstring server) { |
---|
| 55 | int status; |
---|
| 56 | char buffer[1024]; |
---|
| 57 | const char *aserver = (*env)->GetStringUTFChars(env, server, 0); |
---|
| 58 | if (strlen(aserver) > sizeof(buffer)) abort(); |
---|
| 59 | strcpy(buffer, aserver); |
---|
| 60 | (*env)->ReleaseStringUTFChars(env, server, aserver); |
---|
| 61 | status = mr_connect(buffer); |
---|
| 62 | if (status != MR_SUCCESS) throwMoiraException(env, status); |
---|
| 63 | status = mr_version(2); |
---|
| 64 | if (status != MR_SUCCESS) { |
---|
| 65 | if (status == MR_VERSION_LOW) return; /* This is OK */ |
---|
| 66 | else { |
---|
| 67 | mr_disconnect(); |
---|
| 68 | throwMoiraException(env, status); |
---|
| 69 | } |
---|
| 70 | } |
---|
| 71 | return; |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_proxy(JNIEnv *env, |
---|
| 75 | jclass Class, |
---|
| 76 | jstring jUser) { |
---|
| 77 | int status; |
---|
| 78 | char buffer[1024]; |
---|
| 79 | const char *user = (*env)->GetStringUTFChars(env, jUser, 0); |
---|
| 80 | if (strlen(user) > sizeof(buffer)) abort(); |
---|
| 81 | strcpy(buffer, user); |
---|
| 82 | (*env)->ReleaseStringUTFChars(env, jUser, user); |
---|
| 83 | status = mr_proxy(buffer, "Java"); |
---|
| 84 | if (status != MR_SUCCESS) throwMoiraException(env, status); |
---|
| 85 | return; |
---|
| 86 | } |
---|
| 87 | |
---|
| 88 | |
---|
| 89 | JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_auth(JNIEnv *env, |
---|
| 90 | jclass Class) { |
---|
| 91 | int status; |
---|
| 92 | status = mr_krb5_auth("JavaInterface"); |
---|
| 93 | if (status != MR_SUCCESS) throwMoiraException(env, status); |
---|
| 94 | return; |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_disconnect |
---|
| 98 | (JNIEnv *env, jclass Class) { |
---|
| 99 | mr_disconnect(); |
---|
| 100 | return; |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | typedef struct ArgBlock { |
---|
| 104 | int alloccount; |
---|
| 105 | int count; |
---|
| 106 | char **stringval; |
---|
| 107 | } ArgBlock; |
---|
| 108 | |
---|
| 109 | typedef struct ListBlock { |
---|
| 110 | int alloccount; |
---|
| 111 | int count; |
---|
| 112 | ArgBlock **Args; |
---|
| 113 | } ListBlock; |
---|
| 114 | |
---|
| 115 | static jobjectArray ArgBlockToJavaArray(JNIEnv *env, ArgBlock *argb); |
---|
| 116 | static jobjectArray ListBlockToJavaArray(JNIEnv *env, ListBlock *lb); |
---|
| 117 | |
---|
| 118 | extern int mr_query(char *name, int argc, char **argv, |
---|
| 119 | int (*proc)(int, char **, void *), void *hint); |
---|
| 120 | static ListBlock *NewListBlock(); |
---|
| 121 | static ArgBlock *NewArgBlock(); |
---|
| 122 | static void FreeListBlock(ListBlock *); |
---|
| 123 | static int StashResults(int argc, char **argv, void *callback); |
---|
| 124 | static char **ConvertJavaArgs(JNIEnv *env, jobjectArray jargs); |
---|
| 125 | static void FreeArgs(char **args); |
---|
| 126 | |
---|
| 127 | JNIEXPORT jobjectArray JNICALL Java_mit_moira_MoiraConnectInternal_mr_1query |
---|
| 128 | (JNIEnv *env, jclass Class, jstring jcommand, jobjectArray jargs) { |
---|
| 129 | ListBlock *listblock = NewListBlock(); |
---|
| 130 | jobjectArray retval; |
---|
| 131 | int status; |
---|
| 132 | const char *command; |
---|
| 133 | char icommand[1024]; |
---|
| 134 | char **args = ConvertJavaArgs(env, jargs); |
---|
| 135 | if (args == NULL) return (NULL); /* It probably thru an exception */ |
---|
| 136 | command = (*env)->GetStringUTFChars(env, jcommand, 0); |
---|
| 137 | strncpy(icommand, command, sizeof(icommand)); |
---|
| 138 | |
---|
| 139 | status = mr_query(icommand, (*env)->GetArrayLength(env, jargs), args, |
---|
| 140 | StashResults, listblock); |
---|
| 141 | FreeArgs(args); /* Don't need them anymore */ |
---|
| 142 | if (status != MR_SUCCESS) { |
---|
| 143 | FreeListBlock(listblock); |
---|
| 144 | throwMoiraException(env, status); |
---|
| 145 | return (0); |
---|
| 146 | } |
---|
| 147 | /* if (listblock->count == 0) { / * No such list or empty list * / |
---|
| 148 | FreeListBlock(listblock); |
---|
| 149 | throwMoiraExceptionMess(env, "No Such List or Empty List"); |
---|
| 150 | return(0); |
---|
| 151 | } */ |
---|
| 152 | |
---|
| 153 | if (listblock->count == 0) return (0); |
---|
| 154 | |
---|
| 155 | retval = ListBlockToJavaArray(env, listblock); |
---|
| 156 | FreeListBlock(listblock); |
---|
| 157 | return (retval); |
---|
| 158 | |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | static ArgBlock *NewArgBlock() { |
---|
| 162 | ArgBlock *argb = (ArgBlock *)malloc(sizeof(ArgBlock)); |
---|
| 163 | argb->alloccount = 10; |
---|
| 164 | argb->stringval = (char **) malloc(10 * sizeof(char *)); |
---|
| 165 | argb->count = 0; |
---|
| 166 | return (argb); |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | static void AddArg(ArgBlock *argb, char *arg) { |
---|
| 170 | int i; |
---|
| 171 | if (argb->alloccount <= (argb->count + 1)) { |
---|
| 172 | char **st = malloc((2 * argb->alloccount) * sizeof(char *)); |
---|
| 173 | argb->alloccount *= 2; |
---|
| 174 | for (i = 0; i < argb->count; i++) |
---|
| 175 | st[i] = argb->stringval[i]; |
---|
| 176 | free(argb->stringval); |
---|
| 177 | argb->stringval = st; |
---|
| 178 | } |
---|
| 179 | argb->stringval[argb->count++] = arg; |
---|
| 180 | } |
---|
| 181 | |
---|
| 182 | static ListBlock *NewListBlock() { |
---|
| 183 | ListBlock *list = (ListBlock *)malloc(sizeof(ListBlock)); |
---|
| 184 | list->alloccount = 10; |
---|
| 185 | list->Args = (ArgBlock **) malloc(10 * sizeof(ArgBlock *)); |
---|
| 186 | list->count = 0; |
---|
| 187 | return (list); |
---|
| 188 | } |
---|
| 189 | |
---|
| 190 | static void FreeArgBlock(ArgBlock *argb) { |
---|
| 191 | int i; |
---|
| 192 | for (i = 0; i < argb->count; i++) free(argb->stringval[i]); |
---|
| 193 | free(argb->stringval); |
---|
| 194 | free(argb); |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | static void FreeListBlock(ListBlock *list) { |
---|
| 198 | int i; |
---|
| 199 | for (i = 0; i < list->count; i++) FreeArgBlock(list->Args[i]); |
---|
| 200 | free(list->Args); |
---|
| 201 | free(list); |
---|
| 202 | } |
---|
| 203 | |
---|
| 204 | static jobjectArray ArgBlockToJavaArray(JNIEnv *env, ArgBlock *argb) { |
---|
| 205 | jobjectArray retval; |
---|
| 206 | int i; |
---|
| 207 | retval = (*env)->NewObjectArray(env, argb->count, |
---|
| 208 | (*env)->FindClass(env, "java/lang/String"), |
---|
| 209 | NULL); |
---|
| 210 | for (i = 0; i < argb->count; i++) { |
---|
| 211 | (*env)->SetObjectArrayElement(env, retval, i, |
---|
| 212 | (*env)->NewStringUTF(env, argb->stringval[i])); |
---|
| 213 | } |
---|
| 214 | return (retval); |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | static jobjectArray ListBlockToJavaArray(JNIEnv *env, ListBlock *lb) { |
---|
| 218 | jobjectArray retval; |
---|
| 219 | int i; |
---|
| 220 | retval = (*env)->NewObjectArray(env, lb->count, |
---|
| 221 | (*env)->FindClass(env, "java/lang/Object"), |
---|
| 222 | NULL); |
---|
| 223 | for (i = 0; i < lb->count; i++) |
---|
| 224 | (*env)->SetObjectArrayElement(env, retval, i, |
---|
| 225 | ArgBlockToJavaArray(env, lb->Args[i])); |
---|
| 226 | return (retval); |
---|
| 227 | } |
---|
| 228 | |
---|
| 229 | static int StashResults(int argc, char **argv, void *callback) { |
---|
| 230 | ListBlock *list = (ListBlock *) callback; |
---|
| 231 | ArgBlock *argb; |
---|
| 232 | char *arg; |
---|
| 233 | int i; |
---|
| 234 | |
---|
| 235 | /* printf("DEBUG: StashResults argc = %d\n", argc); |
---|
| 236 | * for (i = 0; i < argc; i++) |
---|
| 237 | * printf("DEBUG: StashResults argv[%d] = %s\n", i, argv[i]); |
---|
| 238 | */ |
---|
| 239 | |
---|
| 240 | while (list->alloccount <= (list->count + 1)) { |
---|
| 241 | ArgBlock **args = (ArgBlock **) malloc(list->alloccount * 2 * sizeof(char *)); |
---|
| 242 | list->alloccount = list->alloccount * 2; |
---|
| 243 | for(i = 0; i < list->count; i++) { |
---|
| 244 | args[i] = list->Args[i]; |
---|
| 245 | } |
---|
| 246 | free(list->Args); |
---|
| 247 | list->Args = args; |
---|
| 248 | } |
---|
| 249 | |
---|
| 250 | argb = NewArgBlock(); |
---|
| 251 | |
---|
| 252 | for (i = 0; i < argc; i++) { |
---|
| 253 | arg = (char *) malloc(strlen(argv[i]) + 1); |
---|
| 254 | strcpy(arg, argv[i]); |
---|
| 255 | AddArg(argb, arg); |
---|
| 256 | } |
---|
| 257 | list->Args[list->count++] = argb; |
---|
| 258 | return (0); |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | static char **ConvertJavaArgs(JNIEnv *env, jobjectArray jargs) { |
---|
| 262 | char **retval; |
---|
| 263 | int i, j; |
---|
| 264 | const char *iarg; |
---|
| 265 | int length = (*env)->GetArrayLength(env, jargs); |
---|
| 266 | if (length == 0) { /* Does this happen in a non-error situation? */ |
---|
| 267 | retval = (char **) malloc(sizeof (char *)); |
---|
| 268 | retval[0] = NULL; |
---|
| 269 | return(retval); |
---|
| 270 | } |
---|
| 271 | retval = (char **) malloc((length + 1) * sizeof(char *)); |
---|
| 272 | for (i = 0; i < length; i++) { |
---|
| 273 | jobject jarg = (*env)->GetObjectArrayElement(env, jargs, i); |
---|
| 274 | if ((*env)->ExceptionOccurred(env)) { |
---|
| 275 | for (j = 0; j < i; j++) free(retval[j]); |
---|
| 276 | free (retval); |
---|
| 277 | return (NULL); |
---|
| 278 | } |
---|
| 279 | iarg = (*env)->GetStringUTFChars(env, jarg, 0); |
---|
| 280 | if ((*env)->ExceptionOccurred(env)) { |
---|
| 281 | for (j = 0; j < i; j++) free(retval[j]); |
---|
| 282 | free (retval); |
---|
| 283 | return (NULL); |
---|
| 284 | } |
---|
| 285 | retval[i] = malloc(strlen(iarg) + 1); |
---|
| 286 | strcpy(retval[i], iarg); |
---|
| 287 | (*env)->ReleaseStringUTFChars(env, jarg, iarg); |
---|
| 288 | } |
---|
| 289 | retval[length] = NULL; |
---|
| 290 | return (retval); |
---|
| 291 | } |
---|
| 292 | |
---|
| 293 | static void FreeArgs(char **args) { |
---|
| 294 | int i; |
---|
| 295 | i = 0; |
---|
| 296 | while (args[i] != NULL) free(args[i++]); |
---|
| 297 | free(args); |
---|
| 298 | } |
---|
| 299 | |
---|