| |
| #include <curl/curl.h> /* libcurl header */ |
| #include "CurlGlue.h" /* the JNI-generated glue header file */ |
| |
| /* |
| * This is a private struct allocated for every 'CurlGlue' object. |
| */ |
| struct javacurl { |
| void *libcurl; |
| void *whatever; |
| struct writecallback { |
| jmethodID mid; |
| JNIEnv *java; |
| jclass cls; /* global reference */ |
| jobject object; |
| } write; |
| }; |
| |
| JNIEXPORT jint JNICALL Java_CurlGlue_jni_1init(JNIEnv *java, |
| jobject myself) |
| { |
| void *libhandle; |
| struct javacurl *jcurl=NULL; |
| |
| libhandle = curl_easy_init(); |
| |
| if(libhandle) { |
| jcurl=(struct javacurl *)malloc(sizeof(struct javacurl)); |
| if(jcurl) { |
| memset(jcurl, 0, sizeof(struct javacurl)); |
| jcurl->libcurl = libhandle; |
| |
| } |
| else { |
| curl_easy_cleanup(libhandle); |
| return (jint)0; |
| } |
| } |
| |
| return (jint) jcurl; /* nasty typecast */ |
| } |
| |
| JNIEXPORT void JNICALL Java_CurlGlue_jni_1cleanup(JNIEnv *java, |
| jobject myself, |
| jint jcurl) |
| { |
| |
| struct javacurl *curl = (struct javacurl*)jcurl; |
| |
| if(curl->write.cls) { |
| /* a global reference we must delete */ |
| (*java)->DeleteGlobalRef(java, curl->write.cls); |
| (*java)->DeleteGlobalRef(java, curl->write.object); |
| } |
| |
| curl_easy_cleanup(curl->libcurl); /* cleanup libcurl stuff */ |
| |
| free((void *)curl); /* free the struct too */ |
| } |
| |
| /* |
| * setopt() int + string |
| */ |
| JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILjava_lang_String_2 |
| (JNIEnv *java, jobject myself, jint jcurl, jint option, jstring value) |
| { |
| /* get the actual string C-style */ |
| const char *str = (*java)->GetStringUTFChars(java, value, 0); |
| |
| void *handle = (void *)((struct javacurl*)jcurl)->libcurl; |
| |
| puts("setopt int + string"); |
| |
| return (jint)curl_easy_setopt(handle, (CURLoption)option, str); |
| |
| } |
| |
| /* |
| * setopt() int + int |
| */ |
| JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__III |
| (JNIEnv *java, jobject myself, jint jcurl, jint option, jint value) |
| { |
| void *handle = (void *)((struct javacurl*)jcurl)->libcurl; |
| CURLoption opt = (CURLoption)option; |
| |
| puts("setopt int + int"); |
| |
| switch(opt) { |
| case CURLOPT_FILE: |
| /* silently ignored, we don't need user-specified callback data when |
| we have an object, and besides the CURLOPT_FILE is not exported |
| to the java interface */ |
| return 0; |
| } |
| |
| return (jint)curl_easy_setopt(handle, (CURLoption)option, value); |
| } |
| |
| static int javacurl_write_callback(void *ptr, |
| size_t size, |
| size_t nmemb, |
| FILE *stream) |
| { |
| struct javacurl *curl = (struct javacurl *)stream; |
| size_t realsize = size * nmemb; |
| JNIEnv *java = curl->write.java; |
| jbyteArray jb=NULL; |
| int ret=0; |
| |
| fprintf(stderr, "%d bytes data received in callback:\n" |
| "ptr=%p, java=%p cls=%p\n", |
| realsize, curl, java, curl->write.cls); |
| |
| jb=(*java)->NewByteArray(java, realsize); |
| (*java)->SetByteArrayRegion(java, jb, 0, |
| realsize, (jbyte *)ptr); |
| |
| fprintf(stderr, "created byte-array\n"); |
| |
| ret = (*java)->CallIntMethod(java, |
| curl->write.object, |
| curl->write.mid, |
| jb); |
| |
| fprintf(stderr, "java-method returned %d\n", ret); |
| |
| return realsize; |
| } |
| |
| /* |
| * setopt() int + object |
| */ |
| |
| JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILCurlWrite_2 |
| (JNIEnv *java, jobject myself, jint jcurl, jint option, jobject object) |
| { |
| jclass cls_local = (*java)->GetObjectClass(java, object); |
| jmethodID mid; |
| struct javacurl *curl = (struct javacurl *)jcurl; |
| jclass cls; |
| jobject obj_global; |
| |
| switch(option) { |
| case CURLOPT_WRITEFUNCTION: |
| /* this makes a reference that'll be alive until we kill it! */ |
| cls = (*java)->NewGlobalRef(java, cls_local); |
| |
| printf("setopt int + object, option = %d cls= %p\n", |
| option, cls); |
| |
| if(!cls) { |
| puts("couldn't make local reference global"); |
| return 0; |
| } |
| |
| /* this is the write callback */ |
| mid = (*java)->GetMethodID(java, cls, "handleString", "([B)I"); |
| if(!mid) { |
| puts("no callback method found"); |
| return 0; |
| } |
| |
| obj_global = (*java)->NewGlobalRef(java, object); |
| |
| curl->write.mid = mid; |
| curl->write.cls = cls; |
| curl->write.object = obj_global; |
| /*curl->write.java = java; stored on perform */ |
| |
| fprintf(stderr, "setopt write callback and write file pointer %p, java = %p\n", |
| curl, java); |
| |
| curl_easy_setopt(curl->libcurl, CURLOPT_WRITEFUNCTION, |
| javacurl_write_callback); |
| curl_easy_setopt(curl->libcurl, CURLOPT_FILE, |
| curl); |
| |
| break; |
| } |
| return 0; |
| } |
| |
| JNIEXPORT jint JNICALL Java_CurlGlue_getinfo |
| (JNIEnv *java, jobject value) |
| { |
| return 0; |
| } |
| |
| JNIEXPORT jint JNICALL Java_CurlGlue_jni_1perform |
| (JNIEnv *java, jobject myself, jint jcurl) |
| { |
| struct javacurl *curl=(struct javacurl*)jcurl; |
| curl->write.java = java; |
| return (jint)curl_easy_perform(curl->libcurl); |
| } |