#include "config.h"
#include "JNIBridge.h"
#if ENABLE(MAC_JAVA_BRIDGE)
#include "CString.h"
#include "StringBuilder.h"
#ifdef NDEBUG
#define JS_LOG(formatAndArgs...) ((void)0)
#else
#define JS_LOG(formatAndArgs...) { \
fprintf(stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
fprintf(stderr, formatAndArgs); \
}
#endif
using namespace JSC;
using namespace JSC::Bindings;
using namespace WebCore;
JavaParameter::JavaParameter(JNIEnv* env, jstring type)
{
m_type = JavaString(env, type);
m_JNIType = JNITypeFromClassName(m_type.UTF8String());
}
JavaMethod::JavaMethod(JNIEnv* env, jobject aMethod)
{
jstring returnTypeName = 0;
if (jobject returnType = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;")) {
returnTypeName = static_cast<jstring>(callJNIMethod<jobject>(returnType, "getName", "()Ljava/lang/String;"));
if (!returnTypeName)
returnTypeName = env->NewStringUTF("<Unknown>");
env->DeleteLocalRef(returnType);
}
m_returnType = JavaString(env, returnTypeName);
m_JNIReturnType = JNITypeFromClassName(m_returnType.UTF8String());
env->DeleteLocalRef(returnTypeName);
jstring methodName = static_cast<jstring>(callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;"));
if (!returnTypeName)
returnTypeName = env->NewStringUTF("<Unknown>");
m_name = JavaString(env, methodName);
env->DeleteLocalRef(methodName);
if (jarray jparameters = static_cast<jarray>(callJNIMethod<jobject>(aMethod, "getParameterTypes", "()[Ljava/lang/Class;"))) {
m_numParameters = env->GetArrayLength(jparameters);
m_parameters = new JavaParameter[m_numParameters];
for (int i = 0; i < m_numParameters; i++) {
jobject aParameter = env->GetObjectArrayElement(static_cast<jobjectArray>(jparameters), i);
jstring parameterName = static_cast<jstring>(callJNIMethod<jobject>(aParameter, "getName", "()Ljava/lang/String;"));
if (!parameterName)
parameterName = env->NewStringUTF("<Unknown>");
m_parameters[i] = JavaParameter(env, parameterName);
env->DeleteLocalRef(aParameter);
env->DeleteLocalRef(parameterName);
}
env->DeleteLocalRef(jparameters);
} else {
m_numParameters = 0;
m_parameters = 0;
}
m_signature = 0;
m_methodID = 0;
jclass modifierClass = env->FindClass("java/lang/reflect/Modifier");
int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I");
m_isStatic = static_cast<bool>(callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers));
env->DeleteLocalRef(modifierClass);
}
JavaMethod::~JavaMethod()
{
if (m_signature)
free(m_signature);
delete[] m_parameters;
};
static void appendClassName(StringBuilder& builder, const char* className)
{
#if USE(JSC)
ASSERT(JSLock::lockCount() > 0);
#endif
char* c = strdup(className);
char* result = c;
while (*c) {
if (*c == '.')
*c = '/';
c++;
}
builder.append(result);
free(result);
}
const char* JavaMethod::signature() const
{
if (!m_signature) {
#if USE(JSC)
JSLock lock(SilenceAssertionsOnly);
#endif
StringBuilder signatureBuilder;
signatureBuilder.append("(");
for (int i = 0; i < m_numParameters; i++) {
JavaParameter* aParameter = parameterAt(i);
JNIType type = aParameter->getJNIType();
if (type == array_type)
appendClassName(signatureBuilder, aParameter->type());
else {
signatureBuilder.append(signatureFromPrimitiveType(type));
if (type == object_type) {
appendClassName(signatureBuilder, aParameter->type());
signatureBuilder.append(";");
}
}
}
signatureBuilder.append(")");
const char* returnType = m_returnType.UTF8String();
if (m_JNIReturnType == array_type)
appendClassName(signatureBuilder, returnType);
else {
signatureBuilder.append(signatureFromPrimitiveType(m_JNIReturnType));
if (m_JNIReturnType == object_type) {
appendClassName(signatureBuilder, returnType);
signatureBuilder.append(";");
}
}
String signatureString = signatureBuilder.toString();
m_signature = strdup(signatureString.utf8().data());
}
return m_signature;
}
JNIType JavaMethod::JNIReturnType() const
{
return m_JNIReturnType;
}
jmethodID JavaMethod::methodID(jobject obj) const
{
if (!m_methodID)
m_methodID = getMethodID(obj, m_name.UTF8String(), signature());
return m_methodID;
}
#endif // ENABLE(MAC_JAVA_BRIDGE)