From 43dfc703278f6dfbe99825f67151978396a6b6b1 Mon Sep 17 00:00:00 2001 From: Brian West Date: Thu, 1 Nov 2012 15:04:31 -0500 Subject: [PATCH] FS-4745 --resolve --- conf/vanilla/autoload_configs/java.conf.xml | 13 +- .../languages/mod_java/freeswitch_java.cpp | 179 ++++++++++++++++++ src/mod/languages/mod_java/freeswitch_java.h | 11 ++ src/mod/languages/mod_java/mod_java.i | 7 +- .../org/freeswitch/ApplicationLauncher.java | 15 ++ .../org/freeswitch/OriginateStateHandler.java | 22 +++ .../src/org/freeswitch/StateHandler.java | 54 ++++++ 7 files changed, 291 insertions(+), 10 deletions(-) create mode 100644 src/mod/languages/mod_java/src/org/freeswitch/ApplicationLauncher.java create mode 100644 src/mod/languages/mod_java/src/org/freeswitch/OriginateStateHandler.java create mode 100644 src/mod/languages/mod_java/src/org/freeswitch/StateHandler.java diff --git a/conf/vanilla/autoload_configs/java.conf.xml b/conf/vanilla/autoload_configs/java.conf.xml index 3d1a3b5e5b..5f71553e30 100644 --- a/conf/vanilla/autoload_configs/java.conf.xml +++ b/conf/vanilla/autoload_configs/java.conf.xml @@ -1,13 +1,8 @@ - - - + - - - - + diff --git a/src/mod/languages/mod_java/freeswitch_java.cpp b/src/mod/languages/mod_java/freeswitch_java.cpp index d8390b2ade..d8508e145c 100644 --- a/src/mod/languages/mod_java/freeswitch_java.cpp +++ b/src/mod/languages/mod_java/freeswitch_java.cpp @@ -1,5 +1,35 @@ #include "freeswitch_java.h" +jobject originate_state_handler; + +SWITCH_DECLARE(void) setOriginateStateHandler(jobject stateHandler) +{ + JNIEnv *env = NULL; + jint envStatus = javaVM->GetEnv((void**)&env, JNI_VERSION_1_4); + if ( envStatus != JNI_OK ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error getting JNIEnv!\n"); + return; + } + + if ( stateHandler != NULL && originate_state_handler != NULL ) { + const char* errorMessage = "Originate state handler is already registered"; + jclass exceptionClass = env->FindClass("java/util/TooManyListenersException"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, errorMessage); + env->ThrowNew(exceptionClass, errorMessage); + } else if ( stateHandler == NULL && originate_state_handler != NULL ) { + env->DeleteGlobalRef(originate_state_handler); + originate_state_handler = NULL; + } else { + originate_state_handler = env->NewGlobalRef(stateHandler); + if ( originate_state_handler == NULL ) { + const char* errorMessage = "Unable to create global reference for state handler"; + jclass exceptionClass = env->FindClass("java/lang/OutOfMemoryError"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, errorMessage); + env->ThrowNew(exceptionClass, errorMessage); + } + } +} + JavaSession::JavaSession() : CoreSession() { } @@ -328,3 +358,152 @@ done: return status; } +switch_status_t originate_handler_method(switch_core_session_t *session, const char* method) { + if ( originate_state_handler != NULL ) { + JNIEnv *env = NULL; + bool needDetach = false; + + jint envStatus = javaVM->GetEnv((void**)&env, JNI_VERSION_1_4); + if ( envStatus == JNI_EDETACHED ) { + envStatus = javaVM->AttachCurrentThread((void**)&env, NULL); + if ( envStatus == JNI_OK ) needDetach = true; + } + + if ( envStatus != JNI_OK ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error getting JNIEnv!\n"); + return SWITCH_STATUS_FALSE; + } + + jclass handlerClass = env->GetObjectClass(originate_state_handler); + if ( handlerClass == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error getting handler class!\n"); + if ( needDetach ) javaVM->DetachCurrentThread(); + return SWITCH_STATUS_FALSE; + } + + jint result = SWITCH_STATUS_FALSE; + jmethodID handlerMethod = env->GetMethodID(handlerClass, method, "(Ljava/lang/String;)I"); + if ( handlerMethod != NULL ) { + char *uuid = switch_core_session_get_uuid(session); + jstring javaUuid = env->NewStringUTF(uuid); + result = env->CallIntMethod(originate_state_handler, handlerMethod, javaUuid); + env->DeleteLocalRef(javaUuid); + } + + env->DeleteLocalRef(handlerClass); + if ( needDetach ) javaVM->DetachCurrentThread(); + return (switch_status_t)result; + } + + return SWITCH_STATUS_FALSE; +} + +switch_status_t originate_on_init(switch_core_session_t *session) { + return originate_handler_method(session, "onInit"); +} + +switch_status_t originate_on_routing(switch_core_session_t *session) { + return originate_handler_method(session, "onRouting"); +} + +switch_status_t originate_on_execute(switch_core_session_t *session) { + return originate_handler_method(session, "onExecute"); +} + +switch_status_t originate_on_hangup(switch_core_session_t *session) { + if ( originate_state_handler != NULL ) { + JNIEnv *env = NULL; + bool needDetach = false; + + jint envStatus = javaVM->GetEnv((void**)&env, JNI_VERSION_1_4); + if ( envStatus == JNI_EDETACHED ) { + envStatus = javaVM->AttachCurrentThread((void**)&env, NULL); + if ( envStatus == JNI_OK ) needDetach = true; + } + + if ( envStatus != JNI_OK ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error getting JNIEnv!\n"); + return SWITCH_STATUS_FALSE; + } + + jclass handlerClass = env->GetObjectClass(originate_state_handler); + if ( handlerClass == NULL ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error getting handler class!\n"); + if ( needDetach ) javaVM->DetachCurrentThread(); + return SWITCH_STATUS_FALSE; + } + + jint result = SWITCH_STATUS_FALSE; + jmethodID handlerMethod = env->GetMethodID(handlerClass, "onHangup", "(Ljava/lang/String;Ljava/lang/String;)I"); + if ( handlerMethod != NULL ) { + switch_channel_t *channel = switch_core_session_get_channel(session); + const char *uuid = switch_core_session_get_uuid(session); + const char *cause = switch_channel_cause2str(switch_channel_get_cause(channel)); + jstring javaUuid = env->NewStringUTF(uuid); + jstring javaCause = env->NewStringUTF(cause); + result = env->CallIntMethod(originate_state_handler, handlerMethod, javaUuid, javaCause); + env->DeleteLocalRef(javaUuid); + env->DeleteLocalRef(javaCause); + } + + env->DeleteLocalRef(handlerClass); + if ( needDetach ) javaVM->DetachCurrentThread(); + return (switch_status_t)result; + } + + return SWITCH_STATUS_FALSE; +} + +switch_status_t originate_on_exchange_media(switch_core_session_t *session) { + return originate_handler_method(session, "onExchangeMedia"); +} + +switch_status_t originate_on_soft_execute(switch_core_session_t *session) { + return originate_handler_method(session, "onSoftExecute"); +} + +switch_status_t originate_on_consume_media(switch_core_session_t *session) { + return originate_handler_method(session, "onConsumeMedia"); +} + +switch_status_t originate_on_hibernate(switch_core_session_t *session) { + return originate_handler_method(session, "onHibernate"); +} + +switch_status_t originate_on_reset(switch_core_session_t *session) { + return originate_handler_method(session, "onReset"); +} + +switch_status_t originate_on_park(switch_core_session_t *session) { + return originate_handler_method(session, "onPark"); +} + +switch_status_t originate_on_reporting(switch_core_session_t *session) { + return originate_handler_method(session, "onReporting"); +} + +switch_status_t originate_on_destroy(switch_core_session_t *session) { + return originate_handler_method(session, "onDestroy"); +} + +switch_state_handler_table_t originate_state_handlers = { + /*.on_init */ &originate_on_init, + /*.on_routing */ &originate_on_routing, + /*.on_execute */ &originate_on_execute, + /*.on_hangup */ &originate_on_hangup, + /*.on_exchange_media */ &originate_on_exchange_media, + /*.on_soft_execute */ &originate_on_soft_execute, + /*.on_consume_media */ &originate_on_consume_media, + /*.on_hibernate */ &originate_on_hibernate, + /*.on_reset */ &originate_on_reset, + /*.on_park */ &originate_on_park, + /*.on_reporting */ &originate_on_reporting, + /*.on_destroy */ &originate_on_destroy +}; + +int JavaSession::originate(JavaSession* aleg, char* destination, int timeout) { + switch_state_handler_table_t *stateHandlers = NULL; + if ( originate_state_handler != NULL ) stateHandlers = &originate_state_handlers; + return CoreSession::originate(aleg, destination, timeout, stateHandlers); +} + diff --git a/src/mod/languages/mod_java/freeswitch_java.h b/src/mod/languages/mod_java/freeswitch_java.h index e87b5928f0..5d6d138168 100644 --- a/src/mod/languages/mod_java/freeswitch_java.h +++ b/src/mod/languages/mod_java/freeswitch_java.h @@ -6,6 +6,16 @@ extern JavaVM *javaVM; +#ifdef __cplusplus +extern "C" { +#endif + +SWITCH_DECLARE(void) setOriginateStateHandler(jobject stateHandler); + +#ifdef __cplusplus +} +#endif + class JavaSession:public CoreSession { public: JavaSession(); @@ -19,6 +29,7 @@ class JavaSession:public CoreSession { void setHangupHook(jobject hangupHook); virtual void check_hangup_hook(); virtual switch_status_t run_dtmf_callback(void *input, switch_input_type_t itype); + int originate(JavaSession* aleg, char* destination, int timeout); }; #endif diff --git a/src/mod/languages/mod_java/mod_java.i b/src/mod/languages/mod_java/mod_java.i index 42527fd541..858dac8d08 100644 --- a/src/mod/languages/mod_java/mod_java.i +++ b/src/mod/languages/mod_java/mod_java.i @@ -2,6 +2,7 @@ %include ../../../../swig_common.i /** insert the following includes into generated code so it compiles */ %{ +#include "switch.h" #include "switch_cpp.h" #include "freeswitch_java.h" %} @@ -53,7 +54,11 @@ %typemap(javain) char *terminator "$javainput" %typemap(freearg) char *terminator "" - +#define SWITCH_DECLARE(type) type +%javamethodmodifiers CoreSession::originate(CoreSession *, char *, int, switch_state_handler_table_t *) "protected"; +%javaexception ("java.util.TooManyListenersException") setOriginateStateHandler(jobject); +%typemap(jtype) jobject stateHandler "org.freeswitch.StateHandler" +%typemap(jstype) jobject stateHandler "org.freeswitch.StateHandler" %include "enums.swg" %include switch_swigable_cpp.h diff --git a/src/mod/languages/mod_java/src/org/freeswitch/ApplicationLauncher.java b/src/mod/languages/mod_java/src/org/freeswitch/ApplicationLauncher.java new file mode 100644 index 0000000000..0e7ad0abe0 --- /dev/null +++ b/src/mod/languages/mod_java/src/org/freeswitch/ApplicationLauncher.java @@ -0,0 +1,15 @@ +package org.freeswitch.example; + +import org.freeswitch.swig.freeswitch; + +public class ApplicationLauncher { + + public static final void startup(String arg) { + try { + freeswitch.setOriginateStateHandler(OriginateStateHandler.getInstance()); + } catch (Exception e) { + freeswitch.console_log("err", "Error registering originate state handler"); + } + } + +} diff --git a/src/mod/languages/mod_java/src/org/freeswitch/OriginateStateHandler.java b/src/mod/languages/mod_java/src/org/freeswitch/OriginateStateHandler.java new file mode 100644 index 0000000000..dd59515828 --- /dev/null +++ b/src/mod/languages/mod_java/src/org/freeswitch/OriginateStateHandler.java @@ -0,0 +1,22 @@ +package org.freeswitch.example; + +import org.freeswitch.StateHandler.OnHangupHandler; + +public class OriginateStateHandler implements OnHangupHandler { + + private static OriginateStateHandler instance = null; + + public static final OriginateStateHandler getInstance() { + if ( instance == null ) instance = new OriginateStateHandler(); + return instance; + } + + private OriginateStateHandler() { + // hide constructor + } + + public int onHangup(String uuid, String cause) { + return 1; // SWITCH_STATUS_FALSE + } + +} \ No newline at end of file diff --git a/src/mod/languages/mod_java/src/org/freeswitch/StateHandler.java b/src/mod/languages/mod_java/src/org/freeswitch/StateHandler.java new file mode 100644 index 0000000000..b5f9ba2648 --- /dev/null +++ b/src/mod/languages/mod_java/src/org/freeswitch/StateHandler.java @@ -0,0 +1,54 @@ +package org.freeswitch; + +public interface StateHandler { + + public interface OnInitHandler extends StateHandler { + public int onInit(String uuid); + } + + public static interface OnRoutingHandler extends StateHandler { + public int onRouting(String uuid); + } + + public static interface OnExecuteHandler extends StateHandler { + public int onExecute(String uuid); + } + + public static interface OnHangupHandler extends StateHandler { + public int onHangup(String uuid, String cause); + } + + public static interface OnExchangeMediaHandler extends StateHandler { + public int onExchangeMedia(String uuid); + } + + public static interface OnSoftExecuteHandler extends StateHandler { + public int onSoftExecute(String uuid); + } + + public static interface OnConsumeMediaHandler extends StateHandler { + public int onConsumeMedia(String uuid); + } + + public static interface OnHibernateHandler extends StateHandler { + public int onHibernate(String uuid); + } + + public static interface OnResetHandler extends StateHandler { + public int onReset(String uuid); + } + + public static interface OnParkHandler extends StateHandler { + public int onPark(String uuid); + } + + public static interface OnReportingHandler extends StateHandler { + public int onReporting(String uuid); + } + + public static interface OnDestroyHandler extends StateHandler { + public int onDestroy(String uuid); + } + +} +