/*
 * Copyright 2003-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * Copyright 2003 Wily Technology, Inc.
 */

#include    <jni.h>
#include    <jvmti.h>
#include    <stdlib.h>
#include    <string.h>
#include    "JPLISAgent.h"
#include    "JPLISAssert.h"
#include    "Utilities.h"
#include    "Reentrancy.h"
#include    "JavaExceptions.h"

#include    "EncodingSupport.h"
#include    "FileSystemSupport.h"               /* MAXPATHLEN */

#include    "sun_instrument_InstrumentationImpl.h"
#include    "typedefs.h"

/*
 *  The JPLISAgent manages the initialization all of the Java programming language Agents.
 *  It also supports the native method bridge between the JPLIS and the JVMTI.
 *  It maintains a single JVMTI Env that all JPL agents share.
 *  It parses command line requests and creates individual Java agents.
 */


/*
 *  private prototypes
 */

/* Allocates an unformatted JPLIS agent data structure. Returns NULL if allocation fails. */
JPLISAgent *
allocateJPLISAgent(jvmtiEnv *       jvmtiEnv);

/* Initializes an already-allocated JPLIS agent data structure. */
JPLISInitializationError
initializeJPLISAgent(   JPLISAgent *    agent,
                        JavaVM *        vm,
                        jvmtiEnv *      jvmtienv);
/* De-allocates a JPLIS agent data structure. Only used in partial-failure cases at startup;
 * in normal usage the JPLIS agent lives forever
 */
void
deallocateJPLISAgent(   jvmtiEnv *      jvmtienv,
                        JPLISAgent *    agent);

/* Does one-time work to interrogate the JVM about capabilities and cache the answers. */
void
checkCapabilities(JPLISAgent * agent);

/* Takes the elements of the command string (agent class name and options string) and
 * create java strings for them.
 * Returns true if a classname was found. Makes no promises beyond the textual; says nothing about whether
 * the class exists or can be loaded.
 * If return value is true, sets outputClassname to a non-NULL local JNI reference.
 * If return value is true, sets outputOptionsString either to NULL or to a non-NULL local JNI reference.
 * If return value is false, neither output parameter is set.
 */
jboolean
commandStringIntoJavaStrings(  JNIEnv *        jnienv,
                               const char *    classname,
                               const char *    optionsString,
                               jstring *       outputClassname,
                               jstring *       outputOptionsString);

/* Start one Java agent from the supplied parameters.
 * Most of the logic lives in a helper function that lives over in Java code--
 * we pass parameters out to Java and use our own Java helper to actually
 * load the agent and call the premain.
 * Returns true if the Java agent class is loaded and the premain/agentmain method completes
 * with no exceptions, false otherwise.
 */
jboolean
invokeJavaAgentMainMethod( JNIEnv *    jnienv,
                           jobject     instrumentationImpl,
                           jmethodID   agentMainMethod,
                           jstring     className,
                           jstring     optionsString);

/* Once we have loaded the Java agent and called the premain,
 * we can release the copies we have been keeping of the command line
 * data (agent class name and option strings).
 */
void
deallocateCommandLineData(JPLISAgent * agent);

/*
 *  Common support for various class list fetchers.
 */
typedef jvmtiError (*ClassListFetcher)
    (   jvmtiEnv *  jvmtiEnv,
        jobject     classLoader,
        jint *      classCount,
        jclass **   classes);

/* Fetcher that ignores the class loader parameter, and uses the JVMTI to get a list of all classes.
 * Returns a jvmtiError according to the underlying JVMTI service.
 */
jvmtiError
getAllLoadedClassesClassListFetcher(    jvmtiEnv *  jvmtiEnv,
                                        jobject     classLoader,
                                        jint *      classCount,
                                        jclass **   classes);

/* Fetcher that uses the class loader parameter, and uses the JVMTI to get a list of all classes
 * for which the supplied loader is the initiating loader.
 * Returns a jvmtiError according to the underlying JVMTI service.
 */
jvmtiError
getInitiatedClassesClassListFetcher(    jvmtiEnv *  jvmtiEnv,
                                        jobject     classLoader,
                                        jint *      classCount,
                                        jclass **   classes);

/*
 * Common guts for two native methods, which are the same except for the policy for fetching
 * the list of classes.
 * Either returns a local JNI reference to an array of references to java.lang.Class.
 * Can throw, if it does will alter the JNIEnv with an outstanding exception.
 */
jobjectArray
commonGetClassList( JNIEnv *            jnienv,
                    JPLISAgent *        agent,
                    jobject             classLoader,
                    ClassListFetcher    fetcher);


/*
 *  Misc. utilities.
 */

/* Checked exception mapper used by the redefine classes implementation.
 * Allows ClassNotFoundException or UnmodifiableClassException; maps others
 * to InternalError. Can return NULL in an error case.
 */
jthrowable
redefineClassMapper(    JNIEnv *    jnienv,
                        jthrowable  throwableToMap);

/* Turns a buffer of jclass * into a Java array whose elements are java.lang.Class.
 * Can throw, if it does will alter the JNIEnv with an outstanding exception.
 */
jobjectArray
getObjectArrayFromClasses(JNIEnv* jnienv, jclass* classes, jint classCount);


JPLISEnvironment *
getJPLISEnvironment(jvmtiEnv * jvmtienv) {
    JPLISEnvironment * environment  = NULL;
    jvmtiError         jvmtierror   = JVMTI_ERROR_NONE;

    jvmtierror = (*jvmtienv)->GetEnvironmentLocalStorage(
                                            jvmtienv,
                                            (void**)&environment);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);

    if (jvmtierror == JVMTI_ERROR_NONE) {
        jplis_assert(environment != NULL);
        jplis_assert(environment->mJVMTIEnv == jvmtienv);
    } else {
        environment = NULL;
    }
    return environment;
}

/*
 *  OnLoad processing code.
 */

/*
 *  Creates a new JPLISAgent.
 *  Returns error if the agent cannot be created and initialized.
 *  The JPLISAgent* pointed to by agent_ptr is set to the new broker,
 *  or NULL if an error has occurred.
 */
JPLISInitializationError
createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) {
    JPLISInitializationError initerror       = JPLIS_INIT_ERROR_NONE;
    jvmtiEnv *               jvmtienv        = NULL;
    jint                     jnierror        = JNI_OK;

    *agent_ptr = NULL;
    jnierror = (*vm)->GetEnv(  vm,
                               (void **) &jvmtienv,
                               JVMTI_VERSION);
    if ( jnierror != JNI_OK ) {
        initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
    } else {
        JPLISAgent * agent = allocateJPLISAgent(jvmtienv);
        if ( agent == NULL ) {
            initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
        } else {
            initerror = initializeJPLISAgent(  agent,
                                               vm,
                                               jvmtienv);
            if ( initerror == JPLIS_INIT_ERROR_NONE ) {
                *agent_ptr = agent;
            } else {
                deallocateJPLISAgent(jvmtienv, agent);
            }
        }

        /* don't leak envs */
        if ( initerror != JPLIS_INIT_ERROR_NONE ) {
            jvmtiError jvmtierror = (*jvmtienv)->DisposeEnvironment(jvmtienv);
            jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
        }
    }

    return initerror;
}

/*
 *  Allocates a JPLISAgent. Returns NULL if it cannot be allocated
 */
JPLISAgent *
allocateJPLISAgent(jvmtiEnv * jvmtienv) {
  return (JPLISAgent *) allocate( jvmtienv,
                                    sizeof(JPLISAgent));
}

JPLISInitializationError
initializeJPLISAgent(   JPLISAgent *    agent,
                        JavaVM *        vm,
                        jvmtiEnv *      jvmtienv) {
    jvmtiError      jvmtierror = JVMTI_ERROR_NONE;
    jvmtiPhase      phase;

    agent->mJVM                                      = vm;
    agent->mNormalEnvironment.mJVMTIEnv              = jvmtienv;
    agent->mNormalEnvironment.mAgent                 = agent;
    agent->mNormalEnvironment.mIsRetransformer       = JNI_FALSE;
    agent->mRetransformEnvironment.mJVMTIEnv         = NULL;        /* NULL until needed */
    agent->mRetransformEnvironment.mAgent            = agent;
    agent->mRetransformEnvironment.mIsRetransformer  = JNI_TRUE;
    agent->mAgentmainCaller                          = NULL;
    agent->mInstrumentationImpl                      = NULL;
    agent->mPremainCaller                            = NULL;
    agent->mTransform                                = NULL;
    agent->mRedefineAvailable                        = JNI_FALSE;   /* assume no for now */
    agent->mRedefineAdded                            = JNI_FALSE;
    agent->mNativeMethodPrefixAvailable              = JNI_FALSE;   /* assume no for now */
    agent->mNativeMethodPrefixAdded                  = JNI_FALSE;
    agent->mAgentClassName                           = NULL;
    agent->mOptionsString                            = NULL;

    /* make sure we can recover either handle in either direction.
     * the agent has a ref to the jvmti; make it mutual
     */
    jvmtierror = (*jvmtienv)->SetEnvironmentLocalStorage(
                                            jvmtienv,
                                            &(agent->mNormalEnvironment));
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);

    /* check what capabilities are available */
    checkCapabilities(agent);

    /* check phase - if live phase then we don't need the VMInit event */
    jvmtierror == (*jvmtienv)->GetPhase(jvmtienv, &phase);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    if (phase == JVMTI_PHASE_LIVE) {
        return JPLIS_INIT_ERROR_NONE;
    }

    /* now turn on the VMInit event */
    if ( jvmtierror == JVMTI_ERROR_NONE ) {
        jvmtiEventCallbacks callbacks;
        memset(&callbacks, 0, sizeof(callbacks));
        callbacks.VMInit = &eventHandlerVMInit;

        jvmtierror = (*jvmtienv)->SetEventCallbacks( jvmtienv,
                                                     &callbacks,
                                                     sizeof(callbacks));
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    }

    if ( jvmtierror == JVMTI_ERROR_NONE ) {
        jvmtierror = (*jvmtienv)->SetEventNotificationMode(
                                                jvmtienv,
                                                JVMTI_ENABLE,
                                                JVMTI_EVENT_VM_INIT,
                                                NULL /* all threads */);
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    }

    return (jvmtierror == JVMTI_ERROR_NONE)? JPLIS_INIT_ERROR_NONE : JPLIS_INIT_ERROR_FAILURE;
}

void
deallocateJPLISAgent(jvmtiEnv * jvmtienv, JPLISAgent * agent) {
    deallocate(jvmtienv, agent);
}


JPLISInitializationError
recordCommandLineData(  JPLISAgent *    agent,
                        const char *    agentClassName,
                        const char *    optionsString ) {
    JPLISInitializationError    initerror   = JPLIS_INIT_ERROR_NONE;
    char *      ourCopyOfAgentClassName     = NULL;
    char *      ourCopyOfOptionsString      = NULL;

    /* if no actual params, bail out now */
    if ((agentClassName == NULL) || (*agentClassName == 0)) {
        initerror = JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED;
    } else {
        ourCopyOfAgentClassName = allocate(jvmti(agent), strlen(agentClassName)+1);
        if (ourCopyOfAgentClassName == NULL) {
            initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
        } else {
            if (optionsString != NULL) {
                ourCopyOfOptionsString = allocate(jvmti(agent), strlen(optionsString)+1);
                if (ourCopyOfOptionsString == NULL) {
                    deallocate(jvmti(agent), ourCopyOfAgentClassName);
                    initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
                }
            }
        }
    }

    if (initerror == JPLIS_INIT_ERROR_NONE) {
        strcpy(ourCopyOfAgentClassName, agentClassName);
        if (optionsString != NULL) {
            strcpy(ourCopyOfOptionsString, optionsString);
        }
        agent->mAgentClassName = ourCopyOfAgentClassName;
        agent->mOptionsString = ourCopyOfOptionsString;
    }

    return initerror;
}

/*
 *  VMInit processing code.
 */


/*
 * If this call fails, the JVM launch will ultimately be aborted,
 * so we don't have to be super-careful to clean up in partial failure
 * cases.
 */
jboolean
processJavaStart(   JPLISAgent *    agent,
                    JNIEnv *        jnienv) {
    jboolean    result;

    /*
     *  OK, Java is up now. We can start everything that needs Java.
     */

    /*
     *  First make our emergency fallback InternalError throwable.
     */
    result = initializeFallbackError(jnienv);
    jplis_assert(result);

    /*
     *  Now make the InstrumentationImpl instance.
     */
    if ( result ) {
        result = createInstrumentationImpl(jnienv, agent);
        jplis_assert(result);
    }


    /*
     *  Then turn off the VMInit handler and turn on the ClassFileLoadHook.
     *  This way it is on before anyone registers a transformer.
     */
    if ( result ) {
        result = setLivePhaseEventHandlers(agent);
        jplis_assert(result);
    }

    /*
     *  Load the Java agent, and call the premain.
     */
    if ( result ) {
        result = startJavaAgent(agent, jnienv,
                                agent->mAgentClassName, agent->mOptionsString,
                                agent->mPremainCaller);
    }

    /*
     * Finally surrender all of the tracking data that we don't need any more.
     * If something is wrong, skip it, we will be aborting the JVM anyway.
     */
    if ( result ) {
        deallocateCommandLineData(agent);
    }

    return result;
}

jboolean
startJavaAgent( JPLISAgent *    agent,
                JNIEnv *        jnienv,
                const char *    classname,
                const char *    optionsString,
                jmethodID       agentMainMethod) {
    jboolean    success = JNI_FALSE;
    jstring classNameObject = NULL;
    jstring optionsStringObject = NULL;

    success = commandStringIntoJavaStrings(    jnienv,
                                               classname,
                                               optionsString,
                                               &classNameObject,
                                               &optionsStringObject);

    if (success) {
        success = invokeJavaAgentMainMethod(   jnienv,
                                               agent->mInstrumentationImpl,
                                               agentMainMethod,
                                               classNameObject,
                                               optionsStringObject);
    }

    return success;
}

void
deallocateCommandLineData( JPLISAgent * agent) {
    deallocate(jvmti(agent), (void*)agent->mAgentClassName);
    deallocate(jvmti(agent), (void*)agent->mOptionsString);

    /* zero things out so it is easier to see what is going on */
    agent->mAgentClassName = NULL;
    agent->mOptionsString = NULL;
}

/*
 * Create the java.lang.instrument.Instrumentation instance
 * and access information for it (method IDs, etc)
 */
jboolean
createInstrumentationImpl( JNIEnv *        jnienv,
                           JPLISAgent *    agent) {
    jclass      implClass               = NULL;
    jboolean    errorOutstanding        = JNI_FALSE;
    jobject     resultImpl              = NULL;
    jmethodID   premainCallerMethodID   = NULL;
    jmethodID   agentmainCallerMethodID = NULL;
    jmethodID   transformMethodID       = NULL;
    jmethodID   constructorID           = NULL;
    jobject     localReference          = NULL;

    /* First find the class of our implementation */
    implClass = (*jnienv)->FindClass(   jnienv,
                                        JPLIS_INSTRUMENTIMPL_CLASSNAME);
    errorOutstanding = checkForAndClearThrowable(jnienv);
    errorOutstanding = errorOutstanding || (implClass == NULL);
    jplis_assert_msg(!errorOutstanding, "find class on InstrumentationImpl failed");

    if ( !errorOutstanding ) {
        constructorID = (*jnienv)->GetMethodID( jnienv,
                                                implClass,
                                                JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODNAME,
                                                JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODSIGNATURE);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        errorOutstanding = errorOutstanding || (constructorID == NULL);
        jplis_assert_msg(!errorOutstanding, "find constructor on InstrumentationImpl failed");
        }

    if ( !errorOutstanding ) {
        jlong   peerReferenceAsScalar = (jlong)(intptr_t) agent;
        localReference = (*jnienv)->NewObject(  jnienv,
                                                implClass,
                                                constructorID,
                                                peerReferenceAsScalar,
                                                agent->mRedefineAdded,
                                                agent->mNativeMethodPrefixAdded);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        errorOutstanding = errorOutstanding || (localReference == NULL);
        jplis_assert_msg(!errorOutstanding, "call constructor on InstrumentationImpl failed");
    }

    if ( !errorOutstanding ) {
        resultImpl = (*jnienv)->NewGlobalRef(jnienv, localReference);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert_msg(!errorOutstanding, "copy local ref to global ref");
    }

    /* Now look up the method ID for the pre-main caller (we will need this more than once) */
    if ( !errorOutstanding ) {
        premainCallerMethodID = (*jnienv)->GetMethodID( jnienv,
                                                        implClass,
                                                        JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODNAME,
                                                        JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODSIGNATURE);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        errorOutstanding = errorOutstanding || (premainCallerMethodID == NULL);
        jplis_assert_msg(!errorOutstanding, "can't find premain invoker methodID");
    }

    /* Now look up the method ID for the agent-main caller */
    if ( !errorOutstanding ) {
        agentmainCallerMethodID = (*jnienv)->GetMethodID( jnienv,
                                                          implClass,
                                                          JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODNAME,
                                                          JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        errorOutstanding = errorOutstanding || (agentmainCallerMethodID == NULL);
        jplis_assert_msg(!errorOutstanding, "can't find agentmain invoker methodID");
    }

    /* Now look up the method ID for the transform method (we will need this constantly) */
    if ( !errorOutstanding ) {
        transformMethodID = (*jnienv)->GetMethodID( jnienv,
                                                    implClass,
                                                    JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME,
                                                    JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        errorOutstanding = errorOutstanding || (transformMethodID == NULL);
        jplis_assert_msg(!errorOutstanding, "can't find transform methodID");
    }

    if ( !errorOutstanding ) {
        agent->mInstrumentationImpl = resultImpl;
        agent->mPremainCaller       = premainCallerMethodID;
        agent->mAgentmainCaller     = agentmainCallerMethodID;
        agent->mTransform           = transformMethodID;
    }

    return !errorOutstanding;
}

jboolean
commandStringIntoJavaStrings(  JNIEnv *        jnienv,
                               const char *    classname,
                               const char *    optionsString,
                               jstring *       outputClassname,
                               jstring *       outputOptionsString) {
    jstring     classnameJavaString     = NULL;
    jstring     optionsJavaString       = NULL;
    jboolean    errorOutstanding        = JNI_TRUE;

    classnameJavaString = (*jnienv)->NewStringUTF(jnienv, classname);
    errorOutstanding = checkForAndClearThrowable(jnienv);
    jplis_assert_msg(!errorOutstanding, "can't create class name java string");

    if ( !errorOutstanding ) {
        if ( optionsString != NULL) {
            optionsJavaString = (*jnienv)->NewStringUTF(jnienv, optionsString);
            errorOutstanding = checkForAndClearThrowable(jnienv);
            jplis_assert_msg(!errorOutstanding, "can't create options java string");
        }

        if ( !errorOutstanding ) {
            *outputClassname        = classnameJavaString;
            *outputOptionsString    = optionsJavaString;
        }
    }

    return !errorOutstanding;
}


jboolean
invokeJavaAgentMainMethod( JNIEnv *    jnienv,
                           jobject     instrumentationImpl,
                           jmethodID   mainCallingMethod,
                           jstring     className,
                           jstring     optionsString) {
    jboolean errorOutstanding = JNI_FALSE;

    jplis_assert(mainCallingMethod != NULL);
    if ( mainCallingMethod != NULL ) {
        (*jnienv)->CallVoidMethod(  jnienv,
                                    instrumentationImpl,
                                    mainCallingMethod,
                                    className,
                                    optionsString);
        errorOutstanding = checkForThrowable(jnienv);
        if ( errorOutstanding ) {
            logThrowable(jnienv);
        }
        checkForAndClearThrowable(jnienv);
    }
    return !errorOutstanding;
}

jboolean
setLivePhaseEventHandlers(  JPLISAgent * agent) {
    jvmtiEventCallbacks callbacks;
    jvmtiEnv *          jvmtienv = jvmti(agent);
    jvmtiError          jvmtierror;

    /* first swap out the handlers (switch from the VMInit handler, which we do not need,
     * to the ClassFileLoadHook handler, which is what the agents need from now on)
     */
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.ClassFileLoadHook = &eventHandlerClassFileLoadHook;

    jvmtierror = (*jvmtienv)->SetEventCallbacks( jvmtienv,
                                                 &callbacks,
                                                 sizeof(callbacks));
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);


    if ( jvmtierror == JVMTI_ERROR_NONE ) {
        /* turn off VMInit */
        jvmtierror = (*jvmtienv)->SetEventNotificationMode(
                                                    jvmtienv,
                                                    JVMTI_DISABLE,
                                                    JVMTI_EVENT_VM_INIT,
                                                    NULL /* all threads */);
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    }

    if ( jvmtierror == JVMTI_ERROR_NONE ) {
        /* turn on ClassFileLoadHook */
        jvmtierror = (*jvmtienv)->SetEventNotificationMode(
                                                    jvmtienv,
                                                    JVMTI_ENABLE,
                                                    JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
                                                    NULL /* all threads */);
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    }

    return (jvmtierror == JVMTI_ERROR_NONE);
}

/**
 *  Check if the can_redefine_classes capability is available.
 */
void
checkCapabilities(JPLISAgent * agent) {
    jvmtiEnv *          jvmtienv = jvmti(agent);
    jvmtiCapabilities   potentialCapabilities;
    jvmtiError          jvmtierror;

    memset(&potentialCapabilities, 0, sizeof(potentialCapabilities));

    jvmtierror = (*jvmtienv)->GetPotentialCapabilities(jvmtienv, &potentialCapabilities);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);

    if ( jvmtierror == JVMTI_ERROR_NONE ) {
        if ( potentialCapabilities.can_redefine_classes == 1 ) {
            agent->mRedefineAvailable = JNI_TRUE;
        }
        if ( potentialCapabilities.can_set_native_method_prefix == 1 ) {
            agent->mNativeMethodPrefixAvailable = JNI_TRUE;
        }
    }
}

/**
 * Enable native method prefix in one JVM TI environment
 */
void
enableNativeMethodPrefixCapability(jvmtiEnv * jvmtienv) {
    jvmtiCapabilities   desiredCapabilities;
    jvmtiError          jvmtierror;

        jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
        desiredCapabilities.can_set_native_method_prefix = 1;
        jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
}


/**
 * Add the can_set_native_method_prefix capability
 */
void
addNativeMethodPrefixCapability(JPLISAgent * agent) {
    if (agent->mNativeMethodPrefixAvailable && !agent->mNativeMethodPrefixAdded) {
        jvmtiEnv * jvmtienv = agent->mNormalEnvironment.mJVMTIEnv;
        enableNativeMethodPrefixCapability(jvmtienv);

        jvmtienv = agent->mRetransformEnvironment.mJVMTIEnv;
        if (jvmtienv != NULL) {
            enableNativeMethodPrefixCapability(jvmtienv);
        }
        agent->mNativeMethodPrefixAdded = JNI_TRUE;
    }
}

/**
 * Add the can_maintain_original_method_order capability (for testing)
 */
void
addOriginalMethodOrderCapability(JPLISAgent * agent) {
    jvmtiEnv *          jvmtienv = jvmti(agent);
    jvmtiCapabilities   desiredCapabilities;
    jvmtiError          jvmtierror;

    jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    desiredCapabilities.can_maintain_original_method_order = 1;
    jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
}

/**
 * Add the can_redefine_classes capability
 */
void
addRedefineClassesCapability(JPLISAgent * agent) {
    jvmtiEnv *          jvmtienv = jvmti(agent);
    jvmtiCapabilities   desiredCapabilities;
    jvmtiError          jvmtierror;

    if (agent->mRedefineAvailable && !agent->mRedefineAdded) {
        jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
        desiredCapabilities.can_redefine_classes = 1;
        jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);

        /*
         * With mixed premain/agentmain agents then it's possible that the
         * capability was potentially available in the onload phase but
         * subsequently unavailable in the live phase.
         */
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE ||
                     jvmtierror == JVMTI_ERROR_NOT_AVAILABLE);
        if (jvmtierror == JVMTI_ERROR_NONE) {
            agent->mRedefineAdded = JNI_TRUE;
        }
    }
}


/*
 *  Support for the JVMTI callbacks
 */

void
transformClassFile(             JPLISAgent *            agent,
                                JNIEnv *                jnienv,
                                jobject                 loaderObject,
                                const char*             name,
                                jclass                  classBeingRedefined,
                                jobject                 protectionDomain,
                                jint                    class_data_len,
                                const unsigned char*    class_data,
                                jint*                   new_class_data_len,
                                unsigned char**         new_class_data,
                                jboolean                is_retransformer) {
    jboolean        errorOutstanding        = JNI_FALSE;
    jstring         classNameStringObject   = NULL;
    jarray          classFileBufferObject   = NULL;
    jarray          transformedBufferObject = NULL;
    jsize           transformedBufferSize   = 0;
    unsigned char * resultBuffer            = NULL;
    jboolean        shouldRun               = JNI_FALSE;

    /* only do this if we aren't already in the middle of processing a class on this thread */
    shouldRun = tryToAcquireReentrancyToken(
                                jvmti(agent),
                                NULL);  /* this thread */

    if ( shouldRun ) {
        /* first marshall all the parameters */
        classNameStringObject = (*jnienv)->NewStringUTF(jnienv,
                                                        name);
        errorOutstanding = checkForAndClearThrowable(jnienv);
        jplis_assert_msg(!errorOutstanding, "can't create name string");

        if ( !errorOutstanding ) {
            classFileBufferObject = (*jnienv)->NewByteArray(jnienv,
                                                            class_data_len);
            errorOutstanding = checkForAndClearThrowable(jnienv);
            jplis_assert_msg(!errorOutstanding, "can't create byte arrau");
        }

        if ( !errorOutstanding ) {
            jbyte * typedBuffer = (jbyte *) class_data; /* nasty cast, dumb JNI interface, const missing */
                                                        /* The sign cast is safe. The const cast is dumb. */
            (*jnienv)->SetByteArrayRegion(  jnienv,
                                            classFileBufferObject,
                                            0,
                                            class_data_len,
                                            typedBuffer);
            errorOutstanding = checkForAndClearThrowable(jnienv);
            jplis_assert_msg(!errorOutstanding, "can't set byte array region");
        }

        /*  now call the JPL agents to do the transforming */
        /*  potential future optimization: may want to skip this if there are none */
        if ( !errorOutstanding ) {
            jplis_assert(agent->mInstrumentationImpl != NULL);
            jplis_assert(agent->mTransform != NULL);
            transformedBufferObject = (*jnienv)->CallObjectMethod(
                                                jnienv,
                                                agent->mInstrumentationImpl,
                                                agent->mTransform,
                                                loaderObject,
                                                classNameStringObject,
                                                classBeingRedefined,
                                                protectionDomain,
                                                classFileBufferObject,
                                                is_retransformer);
            errorOutstanding = checkForAndClearThrowable(jnienv);
            jplis_assert_msg(!errorOutstanding, "transform method call failed");
        }

        /* Finally, unmarshall the parameters (if someone touched the buffer, tell the JVM) */
        if ( !errorOutstanding ) {
            if ( transformedBufferObject != NULL ) {
                transformedBufferSize = (*jnienv)->GetArrayLength(  jnienv,
                                                                    transformedBufferObject);
                errorOutstanding = checkForAndClearThrowable(jnienv);
                jplis_assert_msg(!errorOutstanding, "can't get array length");

                if ( !errorOutstanding ) {
                    /* allocate the response buffer with the JVMTI allocate call.
                     *  This is what the JVMTI spec says to do for Class File Load hook responses
                     */
                    jvmtiError  allocError = (*(jvmti(agent)))->Allocate(jvmti(agent),
                                                                             transformedBufferSize,
                                                                             &resultBuffer);
                    errorOutstanding = (allocError != JVMTI_ERROR_NONE);
                    jplis_assert_msg(!errorOutstanding, "can't allocate result buffer");
                }

                if ( !errorOutstanding ) {
                    (*jnienv)->GetByteArrayRegion(  jnienv,
                                                    transformedBufferObject,
                                                    0,
                                                    transformedBufferSize,
                                                    (jbyte *) resultBuffer);
                    errorOutstanding = checkForAndClearThrowable(jnienv);
                    jplis_assert_msg(!errorOutstanding, "can't get byte array region");

                    /* in this case, we will not return the buffer to the JVMTI,
                     * so we need to deallocate it ourselves
                     */
                    if ( errorOutstanding ) {
                        deallocate( jvmti(agent),
                                   (void*)resultBuffer);
                    }
                }

                if ( !errorOutstanding ) {
                    *new_class_data_len = (transformedBufferSize);
                    *new_class_data     = resultBuffer;
                }
            }
        }

        /* release the token */
        releaseReentrancyToken( jvmti(agent),
                                NULL);      /* this thread */

    }

    return;
}

/*
 *  Misc. internal utilities.
 */

/*
 *  The only checked exceptions we can throw are ClassNotFoundException and
 *  UnmodifiableClassException. All others map to InternalError.
 */
jthrowable
redefineClassMapper(    JNIEnv *    jnienv,
                        jthrowable  throwableToMap) {
    jthrowable  mappedThrowable = NULL;

    jplis_assert(isSafeForJNICalls(jnienv));
    jplis_assert(!isUnchecked(jnienv, throwableToMap));

    if ( isInstanceofClassName( jnienv,
                                throwableToMap,
                                "java/lang/ClassNotFoundException") ) {
        mappedThrowable = throwableToMap;
    } else {
        if ( isInstanceofClassName( jnienv,
                                throwableToMap,
                                "java/lang/instrument/UnmodifiableClassException")) {
            mappedThrowable = throwableToMap;
        } else {
            jstring message = NULL;

            message = getMessageFromThrowable(jnienv, throwableToMap);
            mappedThrowable = createInternalError(jnienv, message);
        }
    }

    jplis_assert(isSafeForJNICalls(jnienv));
    return mappedThrowable;
}

jobjectArray
getObjectArrayFromClasses(JNIEnv* jnienv, jclass* classes, jint classCount) {
    jclass          classArrayClass = NULL;
    jobjectArray    localArray      = NULL;
    jint            classIndex      = 0;
    jboolean        errorOccurred   = JNI_FALSE;

    /* get the class array class */
    classArrayClass = (*jnienv)->FindClass(jnienv, "java/lang/Class");
    errorOccurred = checkForThrowable(jnienv);

    if (!errorOccurred) {
        jplis_assert_msg(classArrayClass != NULL, "FindClass returned null class");

        /* create the array for the classes */
        localArray = (*jnienv)->NewObjectArray(jnienv, classCount, classArrayClass, NULL);
        errorOccurred = checkForThrowable(jnienv);

        if (!errorOccurred) {
            jplis_assert_msg(localArray != NULL, "NewObjectArray returned null array");

            /* now copy refs to all the classes and put them into the array */
            for (classIndex = 0; classIndex < classCount; classIndex++) {
                /* put class into array */
                (*jnienv)->SetObjectArrayElement(jnienv, localArray, classIndex, classes[classIndex]);
                errorOccurred = checkForThrowable(jnienv);

                if (errorOccurred) {
                    localArray = NULL;
                    break;
                }
            }
        }
    }

    return localArray;
}


/* Return the environment with the retransformation capability.
 * Create it if it doesn't exist.
 * Return NULL if it can't be created.
 */
jvmtiEnv *
retransformableEnvironment(JPLISAgent * agent) {
    jvmtiEnv *          retransformerEnv     = NULL;
    jint                jnierror             = JNI_OK;
    jvmtiCapabilities   desiredCapabilities;
    jvmtiEventCallbacks callbacks;
    jvmtiError          jvmtierror;

    if (agent->mRetransformEnvironment.mJVMTIEnv != NULL) {
        return agent->mRetransformEnvironment.mJVMTIEnv;
    }
    jnierror = (*agent->mJVM)->GetEnv(  agent->mJVM,
                               (void **) &retransformerEnv,
                               JVMTI_VERSION);
    if ( jnierror != JNI_OK ) {
        return NULL;
    }
    jvmtierror = (*retransformerEnv)->GetCapabilities(retransformerEnv, &desiredCapabilities);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    desiredCapabilities.can_retransform_classes = 1;
    if (agent->mNativeMethodPrefixAdded) {
        desiredCapabilities.can_set_native_method_prefix = 1;
    }

    jvmtierror = (*retransformerEnv)->AddCapabilities(retransformerEnv, &desiredCapabilities);
    if (jvmtierror != JVMTI_ERROR_NONE) {
         /* cannot get the capability, dispose of the retransforming environment */
        jvmtierror = (*retransformerEnv)->DisposeEnvironment(retransformerEnv);
        jplis_assert(jvmtierror == JVMTI_ERROR_NOT_AVAILABLE);
        return NULL;
    }
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.ClassFileLoadHook = &eventHandlerClassFileLoadHook;

    jvmtierror = (*retransformerEnv)->SetEventCallbacks(retransformerEnv,
                                                        &callbacks,
                                                        sizeof(callbacks));
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    if (jvmtierror == JVMTI_ERROR_NONE) {
        // install the retransforming environment
        agent->mRetransformEnvironment.mJVMTIEnv = retransformerEnv;

        // Make it for ClassFileLoadHook handling
        jvmtierror = (*retransformerEnv)->SetEnvironmentLocalStorage(
                                                       retransformerEnv,
                                                       &(agent->mRetransformEnvironment));
        jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
        if (jvmtierror == JVMTI_ERROR_NONE) {
            return retransformerEnv;
        }
    }
    return NULL;
}


/*
 *  Underpinnings for native methods
 */

jboolean
isModifiableClass(JNIEnv * jnienv, JPLISAgent * agent, jclass clazz) {
    jvmtiEnv *          jvmtienv = jvmti(agent);
    jvmtiError          jvmtierror;
    jboolean            is_modifiable = JNI_FALSE;

    jvmtierror = (*jvmtienv)->IsModifiableClass( jvmtienv,
                                                 clazz,
                                                 &is_modifiable);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);

    return is_modifiable;
}

jboolean
isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent) {
    return retransformableEnvironment(agent) != NULL;
}

void
setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has) {
    jvmtiEnv *          retransformerEnv     = retransformableEnvironment(agent);
    jvmtiError          jvmtierror;

    jplis_assert(retransformerEnv != NULL);
    jvmtierror = (*retransformerEnv)->SetEventNotificationMode(
                                                    retransformerEnv,
                                                    has? JVMTI_ENABLE : JVMTI_DISABLE,
                                                    JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
                                                    NULL /* all threads */);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
}

void
retransformClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classes) {
    jvmtiEnv *  retransformerEnv     = retransformableEnvironment(agent);
    jboolean    errorOccurred        = JNI_FALSE;
    jvmtiError  errorCode            = JVMTI_ERROR_NONE;
    jsize       numClasses           = 0;
    jclass *    classArray           = NULL;

    /* This is supposed to be checked by caller, but just to be sure */
    if (retransformerEnv == NULL) {
        jplis_assert(retransformerEnv != NULL);
        errorOccurred = JNI_TRUE;
        errorCode = JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
    }

    /* This was supposed to be checked by caller too */
    if (!errorOccurred && classes == NULL) {
        jplis_assert(classes != NULL);
        errorOccurred = JNI_TRUE;
        errorCode = JVMTI_ERROR_NULL_POINTER;
    }

    if (!errorOccurred) {
        numClasses = (*jnienv)->GetArrayLength(jnienv, classes);
        errorOccurred = checkForThrowable(jnienv);
        jplis_assert(!errorOccurred);
    }

    if (!errorOccurred) {
        classArray = (jclass *) allocate(retransformerEnv,
                                         numClasses * sizeof(jclass));
        errorOccurred = (classArray == NULL);
        jplis_assert(!errorOccurred);
        if (errorOccurred) {
            errorCode = JVMTI_ERROR_OUT_OF_MEMORY;
        }
    }

    if (!errorOccurred) {
        jint index;
        for (index = 0; index < numClasses; index++) {
            classArray[index] = (*jnienv)->GetObjectArrayElement(jnienv, classes, index);
            errorOccurred = checkForThrowable(jnienv);
            jplis_assert(!errorOccurred);
            if (errorOccurred) {
                break;
            }
        }
    }

    if (!errorOccurred) {
        errorCode = (*retransformerEnv)->RetransformClasses(retransformerEnv,
                                                            numClasses, classArray);
        errorOccurred = (errorCode != JVMTI_ERROR_NONE);
    }

    /* Give back the buffer if we allocated it.  Throw any exceptions after.
     */
    if (classArray != NULL) {
        deallocate(retransformerEnv, (void*)classArray);
    }

    if (errorCode != JVMTI_ERROR_NONE) {
        createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
    }

    mapThrownThrowableIfNecessary(jnienv, redefineClassMapper);
}

/*
 *  Java code must not call this with a null list or a zero-length list.
 */
void
redefineClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classDefinitions) {
    jvmtiEnv*   jvmtienv                        = jvmti(agent);
    jboolean    errorOccurred                   = JNI_FALSE;
    jclass      classDefClass                   = NULL;
    jmethodID   getDefinitionClassMethodID      = NULL;
    jmethodID   getDefinitionClassFileMethodID  = NULL;
    jvmtiClassDefinition* classDefs             = NULL;
    jsize       numDefs                         = 0;

    jplis_assert(classDefinitions != NULL);

    numDefs = (*jnienv)->GetArrayLength(jnienv, classDefinitions);
    errorOccurred = checkForThrowable(jnienv);
    jplis_assert(!errorOccurred);

    if (!errorOccurred) {
        jplis_assert(numDefs > 0);
        /* get method IDs for methods to call on class definitions */
        classDefClass = (*jnienv)->FindClass(jnienv, "java/lang/instrument/ClassDefinition");
        errorOccurred = checkForThrowable(jnienv);
        jplis_assert(!errorOccurred);
    }

    if (!errorOccurred) {
        getDefinitionClassMethodID = (*jnienv)->GetMethodID(    jnienv,
                                                classDefClass,
                                                "getDefinitionClass",
                                                "()Ljava/lang/Class;");
        errorOccurred = checkForThrowable(jnienv);
        jplis_assert(!errorOccurred);
    }

    if (!errorOccurred) {
        getDefinitionClassFileMethodID = (*jnienv)->GetMethodID(    jnienv,
                                                    classDefClass,
                                                    "getDefinitionClassFile",
                                                    "()[B");
        errorOccurred = checkForThrowable(jnienv);
        jplis_assert(!errorOccurred);
    }

    if (!errorOccurred) {
        classDefs = (jvmtiClassDefinition *) allocate(
                                                jvmtienv,
                                                numDefs * sizeof(jvmtiClassDefinition));
        errorOccurred = (classDefs == NULL);
        jplis_assert(!errorOccurred);
        if ( errorOccurred ) {
            createAndThrowThrowableFromJVMTIErrorCode(jnienv, JVMTI_ERROR_OUT_OF_MEMORY);
        }
        else {
            jint i;
            for (i = 0; i < numDefs; i++) {
                jclass      classDef    = NULL;
                jbyteArray  targetFile  = NULL;

                classDef = (*jnienv)->GetObjectArrayElement(jnienv, classDefinitions, i);
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }

                classDefs[i].klass = (*jnienv)->CallObjectMethod(jnienv, classDef, getDefinitionClassMethodID);
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }

                targetFile = (*jnienv)->CallObjectMethod(jnienv, classDef, getDefinitionClassFileMethodID);
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }

                classDefs[i].class_bytes = (unsigned char*)(*jnienv)->GetByteArrayElements(jnienv, targetFile, NULL);
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }

                classDefs[i].class_byte_count = (*jnienv)->GetArrayLength(jnienv, targetFile);
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }
            }

            if (!errorOccurred) {
                jvmtiError  errorCode = JVMTI_ERROR_NONE;
                errorCode = (*jvmtienv)->RedefineClasses(jvmtienv, numDefs, classDefs);
                errorOccurred = (errorCode != JVMTI_ERROR_NONE);
                if ( errorOccurred ) {
                    createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
                }
            }

            /* Give back the buffer if we allocated it.
             */
            deallocate(jvmtienv, (void*)classDefs);
        }
    }

    mapThrownThrowableIfNecessary(jnienv, redefineClassMapper);
}

/* Cheesy sharing. ClassLoader may be null. */
jobjectArray
commonGetClassList( JNIEnv *            jnienv,
                    JPLISAgent *        agent,
                    jobject             classLoader,
                    ClassListFetcher    fetcher) {
    jvmtiEnv *      jvmtienv        = jvmti(agent);
    jboolean        errorOccurred   = JNI_FALSE;
    jvmtiError      jvmtierror      = JVMTI_ERROR_NONE;
    jint            classCount      = 0;
    jclass *        classes         = NULL;
    jobjectArray    localArray      = NULL;

    /* retrieve the classes from the JVMTI agent */
    jvmtierror = (*fetcher)( jvmtienv,
                        classLoader,
                        &classCount,
                        &classes);
    errorOccurred = (jvmtierror != JVMTI_ERROR_NONE);
    jplis_assert(!errorOccurred);

    if ( errorOccurred ) {
        createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
    } else {
        localArray = getObjectArrayFromClasses( jnienv,
                                                classes,
                                                classCount);
        errorOccurred = checkForThrowable(jnienv);
        jplis_assert(!errorOccurred);

        /* do this whether or not we saw a problem */
        deallocate(jvmtienv, (void*)classes);
    }

    mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
    return localArray;

}

jvmtiError
getAllLoadedClassesClassListFetcher(    jvmtiEnv *  jvmtienv,
                                        jobject     classLoader,
                                        jint *      classCount,
                                        jclass **   classes) {
    return (*jvmtienv)->GetLoadedClasses(jvmtienv, classCount, classes);
}

jobjectArray
getAllLoadedClasses(JNIEnv * jnienv, JPLISAgent * agent) {
    return commonGetClassList(  jnienv,
                                agent,
                                NULL,
                                getAllLoadedClassesClassListFetcher);
}

jvmtiError
getInitiatedClassesClassListFetcher(    jvmtiEnv *  jvmtienv,
                                        jobject     classLoader,
                                        jint *      classCount,
                                        jclass **   classes) {
    return (*jvmtienv)->GetClassLoaderClasses(jvmtienv, classLoader, classCount, classes);
}


jobjectArray
getInitiatedClasses(JNIEnv * jnienv, JPLISAgent * agent, jobject classLoader) {
    return commonGetClassList(  jnienv,
                                agent,
                                classLoader,
                                getInitiatedClassesClassListFetcher);
}

jlong
getObjectSize(JNIEnv * jnienv, JPLISAgent * agent, jobject objectToSize) {
    jvmtiEnv *  jvmtienv    = jvmti(agent);
    jlong       objectSize  = -1;
    jvmtiError  jvmtierror  = JVMTI_ERROR_NONE;

    jvmtierror = (*jvmtienv)->GetObjectSize(jvmtienv, objectToSize, &objectSize);
    jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
    if ( jvmtierror != JVMTI_ERROR_NONE ) {
        createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
    }

    mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
    return objectSize;
}

void
appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, jboolean isBootLoader)
{
    jvmtiEnv *  jvmtienv    = jvmti(agent);
    jboolean    errorOutstanding;
    jvmtiError  jvmtierror;
    const char* utf8Chars;
    jsize       utf8Len;
    jboolean    isCopy;
    char        platformChars[MAXPATHLEN];
    int         platformLen;

    utf8Len = (*jnienv)->GetStringUTFLength(jnienv, jarFile);
    errorOutstanding = checkForAndClearThrowable(jnienv);

    if (!errorOutstanding) {
        utf8Chars = (*jnienv)->GetStringUTFChars(jnienv, jarFile, &isCopy);
        errorOutstanding = checkForAndClearThrowable(jnienv);

        if (!errorOutstanding && utf8Chars != NULL) {
            /*
             * JVMTI spec'ed to use modified UTF8. At this time this is not implemented
             * the platform encoding is used.
             */
            platformLen = convertUft8ToPlatformString((char*)utf8Chars, utf8Len, platformChars, MAXPATHLEN);
            if (platformLen < 0) {
                createAndThrowInternalError(jnienv);
                return;
            }

            (*jnienv)->ReleaseStringUTFChars(jnienv, jarFile, utf8Chars);
            errorOutstanding = checkForAndClearThrowable(jnienv);

            if (!errorOutstanding) {

                if (isBootLoader) {
                    jvmtierror = (*jvmtienv)->AddToBootstrapClassLoaderSearch(jvmtienv, platformChars);
                } else {
                    jvmtierror = (*jvmtienv)->AddToSystemClassLoaderSearch(jvmtienv, platformChars);
                }

                if ( jvmtierror != JVMTI_ERROR_NONE ) {
                    createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
                }
            }
        }
    }

    mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
}

/*
 *  Set the prefixes used to wrap native methods (so they can be instrumented).
 *  Each transform can set a prefix, any that have been set come in as prefixArray.
 *  Convert them in native strings in a native array then call JVM TI.
 *  One a given call, this function handles either the prefixes for retransformable
 *  transforms or for normal transforms.
 */
void
setNativeMethodPrefixes(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray prefixArray,
                        jboolean isRetransformable) {
    jvmtiEnv*   jvmtienv;
    jvmtiError  err                             = JVMTI_ERROR_NONE;
    jsize       arraySize;
    jboolean    errorOccurred                   = JNI_FALSE;

    jplis_assert(prefixArray != NULL);

    if (isRetransformable) {
        jvmtienv = agent->mRetransformEnvironment.mJVMTIEnv;
    } else {
        jvmtienv = agent->mNormalEnvironment.mJVMTIEnv;
    }
    arraySize = (*jnienv)->GetArrayLength(jnienv, prefixArray);
    errorOccurred = checkForThrowable(jnienv);
    jplis_assert(!errorOccurred);

    if (!errorOccurred) {
        /* allocate the native to hold the native prefixes */
        const char** prefixes = (const char**) allocate(jvmtienv,
                                                        arraySize * sizeof(char*));
        /* since JNI ReleaseStringUTFChars needs the jstring from which the native
         * string was allocated, we store them in a parallel array */
        jstring* originForRelease = (jstring*) allocate(jvmtienv,
                                                        arraySize * sizeof(jstring));
        errorOccurred = (prefixes == NULL || originForRelease == NULL);
        jplis_assert(!errorOccurred);
        if ( errorOccurred ) {
            createAndThrowThrowableFromJVMTIErrorCode(jnienv, JVMTI_ERROR_OUT_OF_MEMORY);
        }
        else {
            jint inx = 0;
            jint i;
            for (i = 0; i < arraySize; i++) {
                jstring      prefixStr  = NULL;
                const char*  prefix;
                jsize        prefixLen;
                jboolean     isCopy;

                prefixStr = (jstring) ((*jnienv)->GetObjectArrayElement(jnienv,
                                                                        prefixArray, i));
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }
                if (prefixStr == NULL) {
                    continue;
                }

                prefixLen = (*jnienv)->GetStringUTFLength(jnienv, prefixStr);
                errorOccurred = checkForThrowable(jnienv);
                jplis_assert(!errorOccurred);
                if (errorOccurred) {
                    break;
                }

                if (prefixLen > 0) {
                    prefix = (*jnienv)->GetStringUTFChars(jnienv, prefixStr, &isCopy);
                    errorOccurred = checkForThrowable(jnienv);
                    jplis_assert(!errorOccurred);
                    if (!errorOccurred && prefix != NULL) {
                        prefixes[inx] = prefix;
                        originForRelease[inx] = prefixStr;
                        ++inx;
                    }
                }
            }

            err = (*jvmtienv)->SetNativeMethodPrefixes(jvmtienv, inx, (char**)prefixes);
            jplis_assert(err == JVMTI_ERROR_NONE);

            for (i = 0; i < inx; i++) {
              (*jnienv)->ReleaseStringUTFChars(jnienv, originForRelease[i], prefixes[i]);
            }
        }
        deallocate(jvmtienv, (void*)prefixes);
        deallocate(jvmtienv, (void*)originForRelease);
    }
}
