2007-09-25 13:21:17 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2007 , Damjan Jovanovic < d a m j a n d o t j o v a t g m a i l d o t c o m >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( 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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Damjan Jovanovic < d a m j a n d o t j o v a t g m a i l d o t c o m >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Damjan Jovanovic < d a m j a n d o t j o v a t g m a i l d o t c o m >
*
*
* mod_java . c - - Java Module
*
*/
# include <switch.h>
# include <jni.h>
static switch_memory_pool_t * memoryPool = NULL ;
static switch_dso_handle_t * javaVMHandle = NULL ;
JavaVM * javaVM = NULL ;
SWITCH_MODULE_LOAD_FUNCTION ( mod_java_load ) ;
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_java_shutdown ) ;
SWITCH_MODULE_DEFINITION ( mod_java , mod_java_load , mod_java_shutdown , NULL ) ;
static void launch_java ( switch_core_session_t * session , char * data , JNIEnv * env )
{
jclass Launcher = NULL ;
jmethodID launch = NULL ;
jstring uuid = NULL ;
jstring args = NULL ;
Launcher = ( * env ) - > FindClass ( env , " org/freeswitch/Launcher " ) ;
if ( Launcher = = NULL )
{
( * env ) - > ExceptionDescribe ( env ) ;
goto done ;
}
launch = ( * env ) - > GetStaticMethodID ( env , Launcher , " launch " , " (Ljava/lang/String;Ljava/lang/String;)V " ) ;
if ( launch = = NULL )
{
( * env ) - > ExceptionDescribe ( env ) ;
goto done ;
}
uuid = ( * env ) - > NewStringUTF ( env , switch_core_session_get_uuid ( session ) ) ;
if ( uuid = = NULL )
{
( * env ) - > ExceptionDescribe ( env ) ;
goto done ;
}
args = ( * env ) - > NewStringUTF ( env , data ) ;
if ( args = = NULL )
{
( * env ) - > ExceptionDescribe ( env ) ;
goto done ;
}
( * env ) - > CallStaticVoidMethod ( env , Launcher , launch , uuid , args ) ;
if ( ( * env ) - > ExceptionOccurred ( env ) )
( * env ) - > ExceptionDescribe ( env ) ;
done :
if ( args ! = NULL )
( * env ) - > DeleteLocalRef ( env , args ) ;
if ( uuid ! = NULL )
( * env ) - > DeleteLocalRef ( env , uuid ) ;
if ( Launcher ! = NULL )
( * env ) - > DeleteLocalRef ( env , Launcher ) ;
}
static void java_function ( switch_core_session_t * session , char * data )
{
JNIEnv * env ;
jint res ;
if ( javaVM = = NULL )
return ;
res = ( * javaVM ) - > AttachCurrentThread ( javaVM , ( void * ) & env , NULL ) ;
if ( res = = JNI_OK )
{
launch_java ( session , data , env ) ;
( * javaVM ) - > DetachCurrentThread ( javaVM ) ;
}
else
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error attaching thread to Java VM! \n " ) ;
}
static switch_application_interface_t java_application_interface = {
/*.interface_name */ " java " ,
/*.application_function */ java_function ,
NULL , NULL , NULL ,
/* flags */ SAF_NONE ,
/* should we support no media mode here? If so, we need to detect the mode, and either disable the media functions or indicate media if/when we need */
/*.next */ NULL
} ;
static switch_loadable_module_interface_t java_module_interface = {
/*.module_name */ modname ,
/*.endpoint_interface */ NULL ,
/*.timer_interface */ NULL ,
/*.dialplan_interface */ NULL ,
/*.codec_interface */ NULL ,
/*.application_interface */ & java_application_interface ,
/*.api_interface */ NULL ,
/*.file_interface */ NULL ,
/*.speech_interface */ NULL ,
/*.directory_interface */ NULL
} ;
static switch_status_t load_config ( JavaVMOption * * javaOptions , int * optionCount )
{
switch_xml_t cfg , xml ;
switch_status_t status ;
xml = switch_xml_open_cfg ( " java.conf " , & cfg , NULL ) ;
if ( xml )
{
switch_xml_t javavm ;
switch_xml_t options ;
javavm = switch_xml_child ( cfg , " javavm " ) ;
if ( javavm ! = NULL )
{
const char * path = switch_xml_attr_soft ( javavm , " path " ) ;
if ( path ! = NULL )
{
status = switch_dso_load ( & javaVMHandle , path , memoryPool ) ;
if ( status ! = SWITCH_STATUS_SUCCESS )
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error loading %s \n " , path ) ;
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No Java VM path specified in java.conf.xml \n " ) ;
status = SWITCH_STATUS_FALSE ;
}
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No Java VM specified in java.conf.xml \n " ) ;
status = SWITCH_STATUS_FALSE ;
goto close ;
}
options = switch_xml_child ( cfg , " options " ) ;
if ( options ! = NULL )
{
switch_xml_t option ;
int i = 0 ;
* optionCount = 0 ;
for ( option = switch_xml_child ( options , " option " ) ; option ; option = option - > next )
{
const char * value = switch_xml_attr_soft ( option , " value " ) ;
if ( value ! = NULL )
+ + * optionCount ;
}
* optionCount + = 1 ;
* javaOptions = switch_core_alloc ( memoryPool , ( switch_size_t ) ( * optionCount * sizeof ( JavaVMOption ) ) ) ;
if ( * javaOptions = = NULL )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Out of memory! \n " ) ;
status = SWITCH_STATUS_FALSE ;
goto close ;
}
for ( option = switch_xml_child ( options , " option " ) ; option ; option = option - > next )
{
const char * value = switch_xml_attr_soft ( option , " value " ) ;
if ( value = = NULL )
continue ;
( * javaOptions ) [ i ] . optionString = switch_core_strdup ( memoryPool , value ) ;
if ( ( * javaOptions ) [ i ] . optionString = = NULL )
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Out of memory! \n " ) ;
status = SWITCH_STATUS_FALSE ;
goto close ;
}
+ + i ;
}
( * javaOptions ) [ i ] . optionString = " -Djava.library.path= " SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR " mod " ;
}
close :
switch_xml_free ( xml ) ;
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error opening java.conf.xml \n " ) ;
status = SWITCH_STATUS_FALSE ;
}
return status ;
}
static switch_status_t create_java_vm ( JavaVMOption * options , int optionCount )
{
jint ( JNICALL * pJNI_CreateJavaVM ) ( JavaVM * * , void * * , void * ) ;
switch_status_t status ;
status = switch_dso_sym ( ( void * ) & pJNI_CreateJavaVM , javaVMHandle , " JNI_CreateJavaVM " ) ;
if ( status = = SWITCH_STATUS_SUCCESS )
{
JNIEnv * env ;
JavaVMInitArgs initArgs ;
jint res ;
memset ( & initArgs , 0 , sizeof ( initArgs ) ) ;
2007-09-26 15:13:47 +00:00
initArgs . version = JNI_VERSION_1_4 ;
2007-09-25 13:21:17 +00:00
initArgs . nOptions = optionCount ;
initArgs . options = options ;
initArgs . ignoreUnrecognized = JNI_TRUE ;
res = pJNI_CreateJavaVM ( & javaVM , ( void * ) & env , & initArgs ) ;
if ( res = = JNI_OK )
{
( * javaVM ) - > DetachCurrentThread ( javaVM ) ;
status = SWITCH_STATUS_SUCCESS ;
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error creating Java VM! \n " ) ;
status = SWITCH_STATUS_FALSE ;
}
}
else
{
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Specified Java VM doesn't have JNI_CreateJavaVM \n " ) ;
status = SWITCH_STATUS_FALSE ;
}
return status ;
}
SWITCH_MODULE_LOAD_FUNCTION ( mod_java_load )
{
switch_status_t status ;
JavaVMOption * options = NULL ;
int optionCount = 0 ;
/* connect my internal structure to the blank pointer passed to me */
* module_interface = & java_module_interface ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Java Framework Loading... \n " ) ;
if ( javaVM ! = NULL )
return SWITCH_STATUS_SUCCESS ;
status = switch_core_new_memory_pool ( & memoryPool ) ;
if ( status = = SWITCH_STATUS_SUCCESS )
{
status = load_config ( & options , & optionCount ) ;
if ( status = = SWITCH_STATUS_SUCCESS )
{
status = create_java_vm ( options , optionCount ) ;
if ( status = = SWITCH_STATUS_SUCCESS )
return SWITCH_STATUS_SUCCESS ;
switch_dso_unload ( javaVMHandle ) ;
}
switch_core_destroy_memory_pool ( & memoryPool ) ;
}
else
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Error creating memory pool \n " ) ;
return status ;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION ( mod_java_shutdown )
{
if ( javaVM = = NULL )
return SWITCH_STATUS_FALSE ;
( * javaVM ) - > DestroyJavaVM ( javaVM ) ;
javaVM = NULL ;
switch_dso_unload ( javaVMHandle ) ;
switch_core_destroy_memory_pool ( & memoryPool ) ;
return SWITCH_STATUS_SUCCESS ;
}