/* 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. */ /* * * @author Mladen Turk * @version $Revision: 473703 $, $Date: 2006-11-11 13:30:52 +0100 (Sat, 11 Nov 2006) $ */ #include "tcn.h" static const char *tcn_errors[] = { "Unknown user error", /* TCN_TIMEUP */ "Operation timed out", /* TCN_EAGAIN */ "There is no data ready", /* TCN_EINTR */ "Interrupted system call", /* TCN_EINPROGRESS */ "Operation in progress", /* TCN_ETIMEDOUT */ "Connection timed out", NULL }; /* Merge IS_ETIMEDOUT with APR_TIMEUP */ #define TCN_STATUS_IS_ETIMEDOUT(x) (APR_STATUS_IS_ETIMEDOUT((x)) || ((x) == APR_TIMEUP)) /* * Convenience function to help throw an java.lang.Exception. */ void tcn_ThrowException(JNIEnv *env, const char *msg) { jclass javaExceptionClass; javaExceptionClass = (*env)->FindClass(env, "java/lang/Exception"); if (javaExceptionClass == NULL) { fprintf(stderr, "Cannot find java/lang/Exception class\n"); return; } (*env)->ThrowNew(env, javaExceptionClass, msg); (*env)->DeleteLocalRef(env, javaExceptionClass); } void tcn_ThrowMemoryException(JNIEnv *env, const char *file, int line, const char *msg) { jclass javaExceptionClass; javaExceptionClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); if (javaExceptionClass == NULL) { fprintf(stderr, "Cannot find java/lang/OutOfMemoryError\n"); return; } if (file) { char fmt[TCN_BUFFER_SZ]; char *f = (char *)(file + strlen(file) - 1); while (f != file && '\\' != *f && '/' != *f) { f--; } if (f != file) { f++; } sprintf(fmt, "%s for [%04d@%s]", msg, line, f); (*env)->ThrowNew(env, javaExceptionClass, &fmt[0]); } else (*env)->ThrowNew(env, javaExceptionClass, msg); (*env)->DeleteLocalRef(env, javaExceptionClass); } void tcn_Throw(JNIEnv *env, const char *fmt, ...) { char msg[TCN_BUFFER_SZ] = {'\0'}; va_list ap; va_start(ap, fmt); apr_vsnprintf(msg, TCN_BUFFER_SZ, fmt, ap); tcn_ThrowException(env, msg); va_end(ap); } /* * Convenience function to help throw an APR Exception * from native error code. */ void tcn_ThrowAPRException(JNIEnv *e, apr_status_t err) { jclass aprErrorClass; jmethodID constructorID = 0; jobject throwObj; jstring jdescription; char serr[512] = {0}; aprErrorClass = (*e)->FindClass(e, TCN_ERROR_CLASS); if (aprErrorClass == NULL) { fprintf(stderr, "Cannot find " TCN_ERROR_CLASS " class\n"); return; } /* Find the constructor ID */ constructorID = (*e)->GetMethodID(e, aprErrorClass, "", "(ILjava/lang/String;)V"); if (constructorID == NULL) { fprintf(stderr, "Cannot find constructor for " TCN_ERROR_CLASS " class\n"); goto cleanup; } apr_strerror(err, serr, 512); /* Obtain the string objects */ jdescription = AJP_TO_JSTRING(serr); if (jdescription == NULL) { fprintf(stderr, "Cannot allocate description for " TCN_ERROR_CLASS " class\n"); goto cleanup; } /* Create the APR Error object */ throwObj = (*e)->NewObject(e, aprErrorClass, constructorID, (jint)err, jdescription); if (throwObj == NULL) { fprintf(stderr, "Cannot allocate new " TCN_ERROR_CLASS " object\n"); goto cleanup; } (*e)->Throw(e, throwObj); cleanup: (*e)->DeleteLocalRef(e, aprErrorClass); } TCN_IMPLEMENT_CALL(jint, Error, osError)(TCN_STDARGS) { UNREFERENCED_STDARGS; return (jint)apr_get_os_error(); } TCN_IMPLEMENT_CALL(jint, Error, netosError)(TCN_STDARGS) { UNREFERENCED_STDARGS; return (jint)apr_get_netos_error(); } TCN_IMPLEMENT_CALL(jstring, Error, strerror)(TCN_STDARGS, jint err) { char serr[512] = {0}; jstring jerr; UNREFERENCED(o); if (err >= TCN_TIMEUP && err <= TCN_ETIMEDOUT) { err -= TCN_TIMEUP; jerr = AJP_TO_JSTRING(tcn_errors[err + 1]); } else { apr_strerror(err, serr, 512); jerr = AJP_TO_JSTRING(serr); } return jerr; } TCN_IMPLEMENT_CALL(jboolean, Status, is)(TCN_STDARGS, jint err, jint idx) { #define APR_IS(I, E) case I: if (E(err)) return JNI_TRUE; break #define APR_ISX(I, E, T) case I: if (E(err) || (err == T)) return JNI_TRUE; break UNREFERENCED_STDARGS; switch (idx) { APR_IS(1, APR_STATUS_IS_ENOSTAT); APR_IS(2, APR_STATUS_IS_ENOPOOL); /* empty slot: +3 */ APR_IS(4, APR_STATUS_IS_EBADDATE); APR_IS(5, APR_STATUS_IS_EINVALSOCK); APR_IS(6, APR_STATUS_IS_ENOPROC); APR_IS(7, APR_STATUS_IS_ENOTIME); APR_IS(8, APR_STATUS_IS_ENODIR); APR_IS(9, APR_STATUS_IS_ENOLOCK); APR_IS(10, APR_STATUS_IS_ENOPOLL); APR_IS(11, APR_STATUS_IS_ENOSOCKET); APR_IS(12, APR_STATUS_IS_ENOTHREAD); APR_IS(13, APR_STATUS_IS_ENOTHDKEY); APR_IS(14, APR_STATUS_IS_EGENERAL); APR_IS(15, APR_STATUS_IS_ENOSHMAVAIL); APR_IS(16, APR_STATUS_IS_EBADIP); APR_IS(17, APR_STATUS_IS_EBADMASK); /* empty slot: +18 */ APR_IS(19, APR_STATUS_IS_EDSOOPEN); APR_IS(20, APR_STATUS_IS_EABSOLUTE); APR_IS(21, APR_STATUS_IS_ERELATIVE); APR_IS(22, APR_STATUS_IS_EINCOMPLETE); APR_IS(23, APR_STATUS_IS_EABOVEROOT); APR_IS(24, APR_STATUS_IS_EBADPATH); APR_IS(25, APR_STATUS_IS_EPATHWILD); APR_IS(26, APR_STATUS_IS_ESYMNOTFOUND); APR_IS(27, APR_STATUS_IS_EPROC_UNKNOWN); APR_IS(28, APR_STATUS_IS_ENOTENOUGHENTROPY); /* APR_Error */ APR_IS(51, APR_STATUS_IS_INCHILD); APR_IS(52, APR_STATUS_IS_INPARENT); APR_IS(53, APR_STATUS_IS_DETACH); APR_IS(54, APR_STATUS_IS_NOTDETACH); APR_IS(55, APR_STATUS_IS_CHILD_DONE); APR_IS(56, APR_STATUS_IS_CHILD_NOTDONE); APR_ISX(57, APR_STATUS_IS_TIMEUP, TCN_TIMEUP); APR_IS(58, APR_STATUS_IS_INCOMPLETE); /* empty slot: +9 */ /* empty slot: +10 */ /* empty slot: +11 */ APR_IS(62, APR_STATUS_IS_BADCH); APR_IS(63, APR_STATUS_IS_BADARG); APR_IS(64, APR_STATUS_IS_EOF); APR_IS(65, APR_STATUS_IS_NOTFOUND); /* empty slot: +16 */ /* empty slot: +17 */ /* empty slot: +18 */ APR_IS(69, APR_STATUS_IS_ANONYMOUS); APR_IS(70, APR_STATUS_IS_FILEBASED); APR_IS(71, APR_STATUS_IS_KEYBASED); APR_IS(72, APR_STATUS_IS_EINIT); APR_IS(73, APR_STATUS_IS_ENOTIMPL); APR_IS(74, APR_STATUS_IS_EMISMATCH); APR_IS(75, APR_STATUS_IS_EBUSY); /* Socket errors */ APR_ISX(90, APR_STATUS_IS_EAGAIN, TCN_EAGAIN); APR_ISX(91, TCN_STATUS_IS_ETIMEDOUT, TCN_ETIMEDOUT); APR_IS(92, APR_STATUS_IS_ECONNABORTED); APR_IS(93, APR_STATUS_IS_ECONNRESET); APR_ISX(94, APR_STATUS_IS_EINPROGRESS, TCN_EINPROGRESS); APR_ISX(95, APR_STATUS_IS_EINTR, TCN_EINTR); APR_IS(96, APR_STATUS_IS_ENOTSOCK); APR_IS(97, APR_STATUS_IS_EINVAL); } return JNI_FALSE; }