/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed 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.
 */

/*
 * java.security.AccessController
 */
#include "Dalvik.h"
#include "native/InternalNativePriv.h"


/*
 * private static ProtectionDomain[] getStackDomains()
 *
 * Return an array of ProtectionDomain objects from the classes of the
 * methods on the stack.  Ignore reflection frames.  Stop at the first
 * privileged frame we see.
 */
static void Dalvik_java_security_AccessController_getStackDomains(
    const u4* args, JValue* pResult)
{
    UNUSED_PARAMETER(args);

    const Method** methods = NULL;
    int length;

    /*
     * Get an array with the stack trace in it.
     */
    if (!dvmCreateStackTraceArray(dvmThreadSelf()->curFrame, &methods, &length))
    {
        LOGE("Failed to create stack trace array\n");
        dvmThrowException("Ljava/lang/InternalError;", NULL);
        RETURN_VOID();
    }

    //int i;
    //LOGI("dvmCreateStackTraceArray results:\n");
    //for (i = 0; i < length; i++)
    //    LOGI(" %2d: %s.%s\n", i, methods[i]->clazz->name, methods[i]->name);

    /*
     * Generate a list of ProtectionDomain objects from the frames that
     * we're interested in.  Skip the first two methods (this method, and
     * the one that called us), and ignore reflection frames.  Stop on the
     * frame *after* the first privileged frame we see as we walk up.
     *
     * We create a new array, probably over-allocated, and fill in the
     * stuff we want.  We could also just run the list twice, but the
     * costs of the per-frame tests could be more expensive than the
     * second alloc.  (We could also allocate it on the stack using C99
     * array creation, but it's not guaranteed to fit.)
     *
     * The array we return doesn't include null ProtectionDomain objects,
     * so we skip those here.
     */
    Object** subSet = (Object**) malloc((length-2) * sizeof(Object*));
    if (subSet == NULL) {
        LOGE("Failed to allocate subSet (length=%d)\n", length);
        free(methods);
        dvmThrowException("Ljava/lang/InternalError;", NULL);
        RETURN_VOID();
    }
    int idx, subIdx = 0;
    for (idx = 2; idx < length; idx++) {
        const Method* meth = methods[idx];
        Object* pd;

        if (dvmIsReflectionMethod(meth))
            continue;

        if (dvmIsPrivilegedMethod(meth)) {
            /* find nearest non-reflection frame; note we skip priv frame */
            //LOGI("GSD priv frame at %s.%s\n", meth->clazz->name, meth->name);
            while (++idx < length && dvmIsReflectionMethod(methods[idx]))
                ;
            length = idx;       // stomp length to end loop
            meth = methods[idx];
        }

        /* get the pd object from the method's class */
        assert(gDvm.offJavaLangClass_pd != 0);
        pd = dvmGetFieldObject((Object*) meth->clazz,
                gDvm.offJavaLangClass_pd);
        //LOGI("FOUND '%s' pd=%p\n", meth->clazz->name, pd);
        if (pd != NULL)
            subSet[subIdx++] = pd;
    }

    //LOGI("subSet:\n");
    //for (i = 0; i < subIdx; i++)
    //    LOGI("  %2d: %s\n", i, subSet[i]->clazz->name);

    /*
     * Create an array object to contain "subSet".
     */
    ClassObject* pdArrayClass = NULL;
    ArrayObject* domains = NULL;
    pdArrayClass = dvmFindArrayClass("[Ljava/security/ProtectionDomain;", NULL);
    if (pdArrayClass == NULL) {
        LOGW("Unable to find ProtectionDomain class for array\n");
        goto bail;
    }
    domains = dvmAllocArray(pdArrayClass, subIdx, kObjectArrayRefWidth,
                ALLOC_DEFAULT);
    if (domains == NULL) {
        LOGW("Unable to allocate pd array (%d elems)\n", subIdx);
        goto bail;
    }

    /* copy the ProtectionDomain objects out */
    Object** objects = (Object**) domains->contents;
    for (idx = 0; idx < subIdx; idx++)
        *objects++ = subSet[idx];

bail:
    free(subSet);
    free(methods);
    dvmReleaseTrackedAlloc((Object*) domains, NULL);
    RETURN_PTR(domains);
}

const DalvikNativeMethod dvm_java_security_AccessController[] = {
    { "getStackDomains",    "()[Ljava/security/ProtectionDomain;",
        Dalvik_java_security_AccessController_getStackDomains },
    { NULL, NULL, NULL },
};

