| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "exception.h" |
| |
| #include <jni.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| jthrowable newExceptionV(JNIEnv* env, const char *name, |
| const char *fmt, va_list ap) |
| { |
| int need; |
| char buf[1], *msg = NULL; |
| va_list ap2; |
| jstring jstr = NULL; |
| jthrowable jthr; |
| jclass clazz; |
| jmethodID excCtor; |
| |
| va_copy(ap2, ap); |
| clazz = (*env)->FindClass(env, name); |
| if (!clazz) { |
| jthr = (*env)->ExceptionOccurred(env); |
| (*env)->ExceptionClear(env); |
| goto done; |
| } |
| excCtor = (*env)->GetMethodID(env, |
| clazz, "<init>", "(Ljava/lang/String;)V"); |
| if (!excCtor) { |
| jthr = (*env)->ExceptionOccurred(env); |
| (*env)->ExceptionClear(env); |
| goto done; |
| } |
| need = vsnprintf(buf, sizeof(buf), fmt, ap); |
| if (need < 0) { |
| fmt = "vsnprintf error"; |
| need = strlen(fmt); |
| } |
| msg = malloc(need + 1); |
| vsnprintf(msg, need + 1, fmt, ap2); |
| jstr = (*env)->NewStringUTF(env, msg); |
| if (!jstr) { |
| jthr = (*env)->ExceptionOccurred(env); |
| (*env)->ExceptionClear(env); |
| goto done; |
| } |
| jthr = (*env)->NewObject(env, clazz, excCtor, jstr); |
| if (!jthr) { |
| jthr = (*env)->ExceptionOccurred(env); |
| (*env)->ExceptionClear(env); |
| goto done; |
| } |
| |
| done: |
| free(msg); |
| va_end(ap2); |
| (*env)->DeleteLocalRef(env, jstr); |
| return jthr; |
| } |
| |
| jthrowable newException(JNIEnv* env, const char *name, const char *fmt, ...) |
| { |
| va_list ap; |
| jthrowable jthr; |
| |
| va_start(ap, fmt); |
| jthr = newExceptionV(env, name, fmt, ap); |
| va_end(ap); |
| return jthr; |
| } |
| |
| jthrowable newRuntimeException(JNIEnv* env, const char *fmt, ...) |
| { |
| va_list ap; |
| jthrowable jthr; |
| |
| va_start(ap, fmt); |
| jthr = newExceptionV(env, "java/lang/RuntimeException", fmt, ap); |
| va_end(ap); |
| return jthr; |
| } |
| |
| jthrowable newIOException(JNIEnv* env, const char *fmt, ...) |
| { |
| va_list ap; |
| jthrowable jthr; |
| |
| va_start(ap, fmt); |
| jthr = newExceptionV(env, "java/io/IOException", fmt, ap); |
| va_end(ap); |
| return jthr; |
| } |
| |
| const char* terror(int errnum) |
| { |
| |
| #if defined(__sun) |
| // MT-Safe under Solaris which doesn't support sys_errlist/sys_nerr |
| return strerror(errnum); |
| #else |
| if ((errnum < 0) || (errnum >= sys_nerr)) { |
| return "unknown error."; |
| } |
| return sys_errlist[errnum]; |
| #endif |
| } |
| |