/* 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$, $Date$
 */

#include "tcn.h"

extern apr_pool_t *tcn_global_pool;

static apr_status_t generic_pool_cleanup(void *data)
{
    apr_status_t rv = APR_SUCCESS;
    tcn_callback_t *cb = (tcn_callback_t *)data;

    if (data) {
        JNIEnv *env;
        tcn_get_java_env(&env);
        if (!TCN_IS_NULL(env, cb->obj)) {
            rv = (*(env))->CallIntMethod(env, cb->obj, cb->mid[0],
                                         NULL);
            TCN_UNLOAD_CLASS(env, cb->obj);
        }
        free(cb);
    }
    return rv;
}

TCN_IMPLEMENT_CALL(jlong, Pool, create)(TCN_STDARGS, jlong parent)
{
    apr_pool_t *p = J2P(parent, apr_pool_t *);
    apr_pool_t *n;

    UNREFERENCED(o);
    /* Make sure our global pool is accessor for all pools */
    if (p == NULL)
        p = tcn_global_pool;
    TCN_THROW_IF_ERR(apr_pool_create(&n, p), n);
cleanup:
    return P2J(n);
}

TCN_IMPLEMENT_CALL(void, Pool, clear)(TCN_STDARGS, jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    UNREFERENCED_STDARGS;
    TCN_ASSERT(pool != 0);
    apr_pool_clear(p);
}

TCN_IMPLEMENT_CALL(void, Pool, destroy)(TCN_STDARGS, jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    UNREFERENCED_STDARGS;
    TCN_ASSERT(pool != 0);
    apr_pool_destroy(p);
}

TCN_IMPLEMENT_CALL(jlong, Pool, parentGet)(TCN_STDARGS, jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    UNREFERENCED_STDARGS;
    TCN_ASSERT(pool != 0);
    return P2J(apr_pool_parent_get(p));
}

TCN_IMPLEMENT_CALL(jboolean, Pool, isAncestor)(TCN_STDARGS, jlong a, jlong b)
{
    apr_pool_t *pa = J2P(a, apr_pool_t *);
    apr_pool_t *pb = J2P(b, apr_pool_t *);
    UNREFERENCED_STDARGS;
    return apr_pool_is_ancestor(pa, pb) ? JNI_TRUE : JNI_FALSE;
}

TCN_IMPLEMENT_CALL(jlong, Pool, palloc)(TCN_STDARGS, jlong pool, jint size)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    UNREFERENCED_STDARGS;
    return P2J(apr_palloc(p, (apr_size_t)size));
}

TCN_IMPLEMENT_CALL(jlong, Pool, pcalloc)(TCN_STDARGS, jlong pool, jint size)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    UNREFERENCED_STDARGS;
    return P2J(apr_pcalloc(p, (apr_size_t)size));
}

TCN_IMPLEMENT_CALL(jlong, Pool, cleanupRegister)(TCN_STDARGS, jlong pool,
                                                 jobject obj)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    tcn_callback_t *cb = (tcn_callback_t *)malloc(sizeof(tcn_callback_t));
    jclass cls;

    UNREFERENCED(o);

    if (cb == NULL) {
       TCN_THROW_OS_ERROR(e);
       return 0;
    }
    cls = (*e)->GetObjectClass(e, obj);
    cb->obj    = (*e)->NewGlobalRef(e, obj);
    cb->mid[0] = (*e)->GetMethodID(e, cls, "callback", "()I");

    apr_pool_cleanup_register(p, (const void *)cb,
                              generic_pool_cleanup,
                              apr_pool_cleanup_null);

    return P2J(cb);
}

TCN_IMPLEMENT_CALL(void, Pool, cleanupKill)(TCN_STDARGS, jlong pool,
                                            jlong data)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    tcn_callback_t *cb = J2P(data, tcn_callback_t *);

    UNREFERENCED(o);
    TCN_ASSERT(pool != 0);
    apr_pool_cleanup_kill(p, cb, generic_pool_cleanup);
    (*e)->DeleteGlobalRef(e, cb->obj);
    free(cb);
}

TCN_IMPLEMENT_CALL(jobject, Pool, alloc)(TCN_STDARGS, jlong pool,
                                         jint size)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    apr_size_t sz = (apr_size_t)size;
    void *mem;

    UNREFERENCED(o);
    TCN_ASSERT(pool != 0);

    if ((mem = apr_palloc(p, sz)) != NULL)
        return (*e)->NewDirectByteBuffer(e, mem, (jlong)sz);
    else
        return NULL;
}

TCN_IMPLEMENT_CALL(jobject, Pool, calloc)(TCN_STDARGS, jlong pool,
                                          jint size)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    apr_size_t sz = (apr_size_t)size;
    void *mem;

    UNREFERENCED(o);
    TCN_ASSERT(pool != 0);

    if ((mem = apr_pcalloc(p, sz)) != NULL)
        return (*e)->NewDirectByteBuffer(e, mem, (jlong)sz);
    else
        return NULL;
}

static apr_status_t generic_pool_data_cleanup(void *data)
{
    apr_status_t rv = APR_SUCCESS;
    tcn_callback_t *cb = (tcn_callback_t *)data;

    if (data) {
        JNIEnv *env;
        tcn_get_java_env(&env);
        
        if (!TCN_IS_NULL(env, cb->obj)) {
            TCN_UNLOAD_CLASS(env, cb->obj);
        }
        free(cb);
    }
    return rv;
}

TCN_IMPLEMENT_CALL(jint, Pool, dataSet)(TCN_STDARGS, jlong pool,
                                        jstring key, jobject data)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    apr_status_t rv = APR_SUCCESS;
    void *old = NULL;
    TCN_ALLOC_CSTRING(key);

    UNREFERENCED(o);
    TCN_ASSERT(pool != 0);

    if (apr_pool_userdata_get(&old, J2S(key), p) == APR_SUCCESS) {
        if (old)
            apr_pool_cleanup_run(p, old, generic_pool_data_cleanup);
    }
    if (data) {
        JNIEnv *e;        
        tcn_callback_t *cb = (tcn_callback_t *)malloc(sizeof(tcn_callback_t));
        tcn_get_java_env(&e);
        cb->obj = (*e)->NewGlobalRef(e, data);
        if ((rv = apr_pool_userdata_set(cb, J2S(key), generic_pool_data_cleanup,
                                        p)) != APR_SUCCESS) {
            (*e)->DeleteGlobalRef(e, cb->obj);
            free(cb);
        }
    }
    else {
        /* Clear the exiting user data */
        rv = apr_pool_userdata_set(NULL, J2S(key), NULL, p);
    }
    TCN_FREE_CSTRING(key);
    return rv;
}

TCN_IMPLEMENT_CALL(jobject, Pool, dataGet)(TCN_STDARGS, jlong pool,
                                           jstring key)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    void *old = NULL;
    TCN_ALLOC_CSTRING(key);
    jobject rv = NULL;

    UNREFERENCED(o);
    TCN_ASSERT(pool != 0);

    if (apr_pool_userdata_get(&old, J2S(key), p) == APR_SUCCESS) {
        if (old) {
            tcn_callback_t *cb = (tcn_callback_t *)old;
            rv = cb->obj;
        }
    }
    TCN_FREE_CSTRING(key);
    return rv;
}

TCN_IMPLEMENT_CALL(void, Pool, cleanupForExec)(TCN_STDARGS)
{
    UNREFERENCED_STDARGS;
    apr_pool_cleanup_for_exec();
}
