/*
* 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 "JavaMethodJobject.h"
#if ENABLE(JAVA_BRIDGE)
#include "JavaString.h"
#if USE(JSC)
#include <runtime/JSObject.h>
#include <runtime/ScopeChain.h>
#endif
#include <wtf/text/StringBuilder.h>
using namespace JSC;
using namespace JSC::Bindings;
JavaMethodJobject::JavaMethodJobject(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_returnTypeClassName = JavaString(env, returnTypeName);
m_returnType = javaTypeFromClassName(m_returnTypeClassName.utf8());
env->DeleteLocalRef(returnTypeName);
// Get method name
jstring methodName = static_cast<jstring>(callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;"));
if (!methodName)
methodName = 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;"))) {
unsigned int numParams = env->GetArrayLength(jparameters);
for (unsigned int i = 0; i < numParams; 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.append(JavaString(env, parameterName).impl());
env->DeleteLocalRef(aParameter);
env->DeleteLocalRef(parameterName);
}
env->DeleteLocalRef(jparameters);
}
// Created lazily.
m_signature = 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);
}
JavaMethodJobject::~JavaMethodJobject()
{
if (m_signature)
fastFree(m_signature);
}
// 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* JavaMethodJobject::signature() const
{
if (!m_signature) {
#if USE(JSC)
JSLock lock(SilenceAssertionsOnly);
#endif
StringBuilder signatureBuilder;
signatureBuilder.append('(');
for (unsigned int i = 0; i < m_parameters.size(); i++) {
CString javaClassName = parameterAt(i).utf8();
JavaType type = javaTypeFromClassName(javaClassName.data());
if (type == JavaTypeArray)
appendClassName(signatureBuilder, javaClassName.data());
else {
signatureBuilder.append(signatureFromJavaType(type));
if (type == JavaTypeObject
// ANDROID
|| type == JavaTypeString
// ANDROID
) {
appendClassName(signatureBuilder, javaClassName.data());
signatureBuilder.append(';');
}
}
}
signatureBuilder.append(')');
const char* returnType = m_returnTypeClassName.utf8();
if (m_returnType == JavaTypeArray)
appendClassName(signatureBuilder, returnType);
else {
signatureBuilder.append(signatureFromJavaType(m_returnType));
if (m_returnType == JavaTypeObject
// ANDROID
|| m_returnType == JavaTypeString
// ANDROID
) {
appendClassName(signatureBuilder, returnType);
signatureBuilder.append(';');
}
}
String signatureString = signatureBuilder.toString();
m_signature = fastStrDup(signatureString.utf8().data());
}
return m_signature;
}
#endif // ENABLE(JAVA_BRIDGE)