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

struct axutil_dll_desc
{
    axis2_char_t *dll_name;
    axis2_char_t *path_qualified_dll_name;
    axis2_dll_type_t dll_type;
    int load_options;
    AXIS2_DLHANDLER dl_handler;
    CREATE_FUNCT create_funct;
    DELETE_FUNCT delete_funct;
    AXIS2_TIME_T timestamp;
    axutil_error_codes_t error_code;

};

AXIS2_EXTERN axutil_dll_desc_t *AXIS2_CALL
axutil_dll_desc_create(
    const axutil_env_t *env)
{
    axutil_dll_desc_t *dll_desc = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    dll_desc = (axutil_dll_desc_t *)AXIS2_MALLOC(env->allocator, sizeof(axutil_dll_desc_t));

    if(!dll_desc)
    {
        AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
        AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Out of memory");
        return NULL;
    }

    dll_desc->dll_name = NULL;
    dll_desc->path_qualified_dll_name = NULL;
    dll_desc->dll_type = 0;
    dll_desc->load_options = 0;
    dll_desc->dl_handler = NULL;
    dll_desc->create_funct = NULL;
    dll_desc->delete_funct = NULL;
    dll_desc->timestamp = 0;
    dll_desc->error_code = AXIS2_ERROR_NONE;

    return dll_desc;
}

AXIS2_EXTERN void AXIS2_CALL
axutil_dll_desc_free(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    if(dll_desc->dl_handler)
    {
        axutil_class_loader_delete_dll(env, dll_desc);
    }

    if(dll_desc->dll_name)
    {
        AXIS2_FREE(env->allocator, dll_desc->dll_name);
        dll_desc->dll_name = NULL;
    }

    if(dll_desc->path_qualified_dll_name)
    {
        AXIS2_FREE(env->allocator, dll_desc->path_qualified_dll_name);
        dll_desc->path_qualified_dll_name = NULL;
    }

    if(dll_desc)
    {
        AXIS2_FREE(env->allocator, dll_desc);
    }
    return;
}

AXIS2_EXTERN void AXIS2_CALL
axutil_dll_desc_free_void_arg(
    void *dll_desc,
    const axutil_env_t *env)
{
    axutil_dll_desc_t *dll_desc_l = NULL;

    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    dll_desc_l = (axutil_dll_desc_t *)dll_desc;
    axutil_dll_desc_free(dll_desc_l, env);
    return;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_name(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    axis2_char_t *name)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, name, AXIS2_FAILURE);

    if(dll_desc->path_qualified_dll_name)
    {
        AXIS2_FREE(env->allocator, dll_desc->path_qualified_dll_name);
        dll_desc->path_qualified_dll_name = NULL;
    }

    dll_desc->path_qualified_dll_name = axutil_strdup(env, name);
    if(!dll_desc->path_qualified_dll_name)
    {
        return AXIS2_FAILURE;
    }
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_dll_desc_get_name(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->path_qualified_dll_name;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_load_options(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    int options)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    dll_desc->load_options = options;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_type(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    axis2_dll_type_t type)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    dll_desc->dll_type = type;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_dll_type_t AXIS2_CALL
axutil_dll_desc_get_type(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->dll_type;
}

AXIS2_EXTERN int AXIS2_CALL
axutil_dll_desc_get_load_options(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->load_options;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_dl_handler(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    AXIS2_DLHANDLER dl_handler)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    AXIS2_PARAM_CHECK(env->error, dl_handler, AXIS2_FAILURE);

    if(dll_desc->dl_handler)
    {
        AXIS2_FREE(env->allocator, dll_desc->dl_handler);
    }
    dll_desc->dl_handler = dl_handler;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN AXIS2_DLHANDLER AXIS2_CALL
axutil_dll_desc_get_dl_handler(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->dl_handler;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_create_funct(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    CREATE_FUNCT funct)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    dll_desc->create_funct = funct;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN CREATE_FUNCT AXIS2_CALL
axutil_dll_desc_get_create_funct(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->create_funct;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_delete_funct(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    DELETE_FUNCT funct)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    dll_desc->delete_funct = funct;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN DELETE_FUNCT AXIS2_CALL
axutil_dll_desc_get_delete_funct(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->delete_funct;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_timestamp(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    AXIS2_TIME_T timestamp)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
    dll_desc->timestamp = timestamp;
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN AXIS2_TIME_T AXIS2_CALL
axutil_dll_desc_get_timestamp(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->timestamp;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
axutil_dll_desc_set_error_code(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    axutil_error_codes_t error_code)
{
    AXIS2_ENV_CHECK(env, AXIS2_FAILURE);

    dll_desc->error_code = error_code;

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axutil_error_codes_t AXIS2_CALL
axutil_dll_desc_get_error_code(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env)
{
    return dll_desc->error_code;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
axutil_dll_desc_create_platform_specific_dll_name(
    axutil_dll_desc_t *dll_desc,
    const axutil_env_t *env,
    const axis2_char_t *class_name)
{
    axis2_char_t *temp_name = NULL;

    AXIS2_ENV_CHECK(env, NULL);

    /* allow config to give a literal lib name since it may want a 
     * versioned lib like "libfoo.so.0" */
    if (axutil_strstr(class_name, AXIS2_LIB_SUFFIX)) {
            /* assume the class_name is the literal lib file name */
            dll_desc->dll_name = axutil_strdup(env,class_name);
            return dll_desc->dll_name;
    }

    temp_name = axutil_stracat(env, AXIS2_LIB_PREFIX, class_name);
    dll_desc->dll_name = axutil_stracat(env, temp_name, AXIS2_LIB_SUFFIX);
    AXIS2_FREE(env->allocator, temp_name);
    return dll_desc->dll_name;
}
