blob: 778d4c3aa7910c9a318740a5091631f72eb39911 [file] [log] [blame]
/*
* Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
* Copyright 2010, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JNIBridge.h"
#if ENABLE(MAC_JAVA_BRIDGE)
#include "CString.h"
#include "StringBuilder.h"
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)
{
// Get return type name
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);
// Get method name
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);
// Get parameters
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;
}
// Created lazily.
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)
fastFree(m_signature);
delete[] m_parameters;
};
// JNI method signatures use '/' between components of a class name, but
// we get '.' between components from the reflection API.
static void appendClassName(StringBuilder& builder, const char* className)
{
#if USE(JSC)
ASSERT(JSLock::lockCount() > 0);
#endif
char* c = fastStrDup(className);
char* result = c;
while (*c) {
if (*c == '.')
*c = '/';
c++;
}
builder.append(result);
fastFree(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 = fastStrDup(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)