/*
 * 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 <axutil_class_loader.h>

axis2_status_t
axutil_class_loader_load_lib(
    const axutil_env_t *env,
    axutil_dll_desc_t *dll_desc);

axis2_status_t
axutil_class_loader_unload_lib(
    const axutil_env_t *env,
    axutil_dll_desc_t *dll_desc);

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_class_loader_init(
    const axutil_env_t *env)
{
    AXIS2_PLATFORM_LOADLIBINIT();
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_class_loader_delete_dll(
    const axutil_env_t *env,
    axutil_dll_desc_t *dll_desc)
{
    if(!dll_desc)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_CREATE_FAILED, AXIS2_FAILURE);
        return AXIS2_FAILURE;
    }
    axutil_class_loader_unload_lib(env, dll_desc);
    AXIS2_PLATFORM_LOADLIBEXIT();
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN void *AXIS2_CALL
axutil_class_loader_create_dll(
    const axutil_env_t *env,
    axutil_param_t *impl_info_param)
{
    void *obj = NULL;
    CREATE_FUNCT create_funct = NULL;
    DELETE_FUNCT delete_funct = NULL;
    AXIS2_DLHANDLER dl_handler = NULL;
    axutil_dll_desc_t *dll_desc = NULL;
    axis2_status_t status = AXIS2_FAILURE;
    axutil_error_codes_t error_code = AXIS2_ERROR_NONE;

    dll_desc = axutil_param_get_value(impl_info_param, env);
    if(!dll_desc)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_CREATE_FAILED, AXIS2_FAILURE);
        return NULL;
    }
    dl_handler = axutil_dll_desc_get_dl_handler(dll_desc, env);
    if(!dl_handler)
    {
        status = axutil_class_loader_load_lib(env, dll_desc);
        if(AXIS2_SUCCESS != status)
        {
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_CREATE_FAILED, AXIS2_FAILURE);
            return NULL;
        }
        dl_handler = axutil_dll_desc_get_dl_handler(dll_desc, env);
        if(!dl_handler)
        {
            return NULL;
        }

        create_funct = (CREATE_FUNCT)AXIS2_PLATFORM_GETPROCADDR(dl_handler, AXIS2_CREATE_FUNCTION);
        if(!create_funct)
        {
            return NULL;
        }
        status = axutil_dll_desc_set_create_funct(dll_desc, env, create_funct);
        if(AXIS2_FAILURE == status)
        {
            axutil_class_loader_unload_lib(env, dll_desc);
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_CREATE_FAILED, AXIS2_FAILURE);
            return NULL;
        }

        delete_funct = (DELETE_FUNCT)AXIS2_PLATFORM_GETPROCADDR(dl_handler, AXIS2_DELETE_FUNCTION);
        if(!delete_funct)
        {
            return NULL;
        }
        status = axutil_dll_desc_set_delete_funct(dll_desc, env, delete_funct);
        if(AXIS2_FAILURE == status)
        {
            axutil_class_loader_unload_lib(env, dll_desc);
            AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_CREATE_FAILED, AXIS2_FAILURE);
            return NULL;
        }
    }
    create_funct = axutil_dll_desc_get_create_funct(dll_desc, env);
    if(!create_funct)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_STATE_DLL_DESC, AXIS2_FAILURE);
        return NULL;
    }
    error_code = axutil_dll_desc_get_error_code(dll_desc, env);

    create_funct(&obj, env);
    if(!obj)
    {
        axutil_class_loader_unload_lib(env, dll_desc);
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Object create function returned NULL");
        AXIS2_ERROR_SET(env->error, error_code, AXIS2_FAILURE);
        return NULL;
    }
    else
    {
        AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "%s shared lib loaded successfully",
            axutil_dll_desc_get_name(dll_desc, env));
    }
	axutil_param_set_param_type(impl_info_param, env, AXIS2_DLL_PARAM);
    return obj;
}

axis2_status_t
axutil_class_loader_load_lib(
    const axutil_env_t * env,
    axutil_dll_desc_t * dll_desc)
{
    axis2_char_t *dll_name = NULL;
    AXIS2_DLHANDLER dl_handler = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    dll_name = axutil_dll_desc_get_name(dll_desc, env);
    dl_handler = AXIS2_PLATFORM_LOADLIB(dll_name);
    if(!dl_handler)
    {
#ifndef WIN32
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Loading shared library %s  Failed. DLERROR IS %s",
            dll_name, AXIS2_PLATFORM_LOADLIB_ERROR);
#else
        axis2_char_t buff[AXUTIL_WIN32_ERROR_BUFSIZE];
        axutil_win32_get_last_error(buff, AXUTIL_WIN32_ERROR_BUFSIZE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Loading shared library %s  Failed. DLERROR IS %s",
            dll_name, buff);
#endif
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_LOADING_FAILED, AXIS2_FAILURE);

        return AXIS2_FAILURE;
    }
    status = axutil_dll_desc_set_dl_handler(dll_desc, env, dl_handler);

    if(AXIS2_SUCCESS != status)
    {
        AXIS2_PLATFORM_UNLOADLIB(dl_handler);
        dl_handler = NULL;
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_DLL_LOADING_FAILED, AXIS2_FAILURE);
        return status;
    }

    return AXIS2_SUCCESS;
}

axis2_status_t
axutil_class_loader_unload_lib(
    const axutil_env_t * env,
    axutil_dll_desc_t * dll_desc)
{
    AXIS2_DLHANDLER dl_handler = axutil_dll_desc_get_dl_handler(dll_desc, env);
    if(dl_handler)
    {
        AXIS2_PLATFORM_UNLOADLIB(dl_handler);
    }

    return AXIS2_SUCCESS;
}
