/**
* @copyright
* ====================================================================
* 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.
* ====================================================================
* @endcopyright
*
* @file JNIStackElement.cpp
* @brief Implementation of the class JNIStackElement
*/
#include "JNIStackElement.h"
#include "JNIUtil.h"
#include "JNIStringHolder.h"
#include "JNIThreadData.h"
#include <apr_strings.h>
/**
* Create a new object and generate a log message,if requested
* @param env the JNI-environment
* @param clazz the class name of the method
* @param method the name of the method
* @param jthis the Java object for which the method is call
*/
JNIStackElement::JNIStackElement(JNIEnv *env, const char *clazz,
const char *method, jobject jthis)
{
JNIUtil::JNIInit(env);
// Generating a log message is expensive.
if (JNIUtil::getLogLevel() >= JNIUtil::entryLog)
{
jclass jlo = env->FindClass("java/lang/Object");
if (JNIUtil::isJavaExceptionThrown())
return;
// The method id will not change during the time this library
// is loaded, so it can be cached.
static jmethodID mid = 0;
if (mid == 0)
{
mid = env->GetMethodID(jlo, "toString", "()Ljava/lang/String;");
if (JNIUtil::isJavaExceptionThrown())
return;
}
*m_objectID = 0;
if(jthis == NULL)
{
strcpy(m_objectID, "<static>");
}
else
{
// This will call java.lang.Object.toString, even when it is
// overriden.
jobject oStr = env->CallNonvirtualObjectMethod(jthis, jlo, mid);
if (JNIUtil::isJavaExceptionThrown())
return;
// Copy the result to a buffer.
JNIStringHolder name(reinterpret_cast<jstring>(oStr));
strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
env->DeleteLocalRef(oStr);
}
// Release the Java string.
env->DeleteLocalRef(jlo);
// Remember the parameter for the exit of the method.
m_clazz = clazz;
m_method = method;
// Generate the log message.
char *buffer = JNIUtil::getFormatBuffer();
apr_snprintf(buffer, JNIUtil::formatBufferSize,
"entry class %s method %s object %s", m_clazz, m_method,
m_objectID);
JNIUtil::logMessage(buffer);
}
else
{
// Initialize the object cleanly.
m_clazz = NULL;
m_method = NULL;
*m_objectID = 0;
}
}
/**
* Destroy an object and create a log message for the exit of the
* method, if one was create for the entry.
*/
JNIStackElement::~JNIStackElement()
{
if (m_clazz != NULL)
{
// Generate a log message.
char *buffer = JNIUtil::getFormatBuffer();
apr_snprintf(buffer, JNIUtil::formatBufferSize,
"exit class %s method %s object %s", m_clazz,
m_method, m_objectID);
JNIUtil::logMessage(buffer);
}
JNIThreadData::popThreadData();
}