18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 24e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved. 34e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block * Copyright 2010, The Android Open Source Project 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 244e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 28e1ac8b286215f0cb7df30bca8d3057d6992f2851Steve Block#include "JNIBridge.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(MAC_JAVA_BRIDGE) 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3276d21c39487c7753f1207935b120f3d4b06bae8dSteve Block#include "CString.h" 3376d21c39487c7753f1207935b120f3d4b06bae8dSteve Block#include "StringBuilder.h" 34a96d9eff8bdc7ed33739f5779a8d40ab1b3ae24fSteve Block 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef NDEBUG 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define JS_LOG(formatAndArgs...) ((void)0) 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define JS_LOG(formatAndArgs...) { \ 404e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block fprintf(stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \ 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project fprintf(stderr, formatAndArgs); \ 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace JSC; 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace JSC::Bindings; 4776d21c39487c7753f1207935b120f3d4b06bae8dSteve Blockusing namespace WebCore; 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 504e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve BlockJavaParameter::JavaParameter(JNIEnv* env, jstring type) 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 524e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_type = JavaString(env, type); 534e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_JNIType = JNITypeFromClassName(m_type.UTF8String()); 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 564e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve BlockJavaMethod::JavaMethod(JNIEnv* env, jobject aMethod) 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 58d0825bca7fe65beaee391d30da42e937db621564Steve Block // Get return type name 59d0825bca7fe65beaee391d30da42e937db621564Steve Block jstring returnTypeName = 0; 60d0825bca7fe65beaee391d30da42e937db621564Steve Block if (jobject returnType = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;")) { 61d0825bca7fe65beaee391d30da42e937db621564Steve Block returnTypeName = static_cast<jstring>(callJNIMethod<jobject>(returnType, "getName", "()Ljava/lang/String;")); 62d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!returnTypeName) 63d0825bca7fe65beaee391d30da42e937db621564Steve Block returnTypeName = env->NewStringUTF("<Unknown>"); 64d0825bca7fe65beaee391d30da42e937db621564Steve Block env->DeleteLocalRef(returnType); 65d0825bca7fe65beaee391d30da42e937db621564Steve Block } 66d0825bca7fe65beaee391d30da42e937db621564Steve Block m_returnType = JavaString(env, returnTypeName); 67d0825bca7fe65beaee391d30da42e937db621564Steve Block m_JNIReturnType = JNITypeFromClassName(m_returnType.UTF8String()); 684e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block env->DeleteLocalRef(returnTypeName); 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Get method name 714e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block jstring methodName = static_cast<jstring>(callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;")); 72d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!returnTypeName) 73d0825bca7fe65beaee391d30da42e937db621564Steve Block returnTypeName = env->NewStringUTF("<Unknown>"); 744e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_name = JavaString(env, methodName); 754e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block env->DeleteLocalRef(methodName); 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Get parameters 78d0825bca7fe65beaee391d30da42e937db621564Steve Block if (jarray jparameters = static_cast<jarray>(callJNIMethod<jobject>(aMethod, "getParameterTypes", "()[Ljava/lang/Class;"))) { 79d0825bca7fe65beaee391d30da42e937db621564Steve Block m_numParameters = env->GetArrayLength(jparameters); 80d0825bca7fe65beaee391d30da42e937db621564Steve Block m_parameters = new JavaParameter[m_numParameters]; 81d0825bca7fe65beaee391d30da42e937db621564Steve Block 82d0825bca7fe65beaee391d30da42e937db621564Steve Block for (int i = 0; i < m_numParameters; i++) { 83d0825bca7fe65beaee391d30da42e937db621564Steve Block jobject aParameter = env->GetObjectArrayElement(static_cast<jobjectArray>(jparameters), i); 84d0825bca7fe65beaee391d30da42e937db621564Steve Block jstring parameterName = static_cast<jstring>(callJNIMethod<jobject>(aParameter, "getName", "()Ljava/lang/String;")); 85d0825bca7fe65beaee391d30da42e937db621564Steve Block if (!parameterName) 86d0825bca7fe65beaee391d30da42e937db621564Steve Block parameterName = env->NewStringUTF("<Unknown>"); 87d0825bca7fe65beaee391d30da42e937db621564Steve Block m_parameters[i] = JavaParameter(env, parameterName); 88d0825bca7fe65beaee391d30da42e937db621564Steve Block env->DeleteLocalRef(aParameter); 89d0825bca7fe65beaee391d30da42e937db621564Steve Block env->DeleteLocalRef(parameterName); 90d0825bca7fe65beaee391d30da42e937db621564Steve Block } 91d0825bca7fe65beaee391d30da42e937db621564Steve Block env->DeleteLocalRef(jparameters); 92d0825bca7fe65beaee391d30da42e937db621564Steve Block } else { 93d0825bca7fe65beaee391d30da42e937db621564Steve Block m_numParameters = 0; 94d0825bca7fe65beaee391d30da42e937db621564Steve Block m_parameters = 0; 95d0825bca7fe65beaee391d30da42e937db621564Steve Block } 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Created lazily. 984e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_signature = 0; 994e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_methodID = 0; 1004e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project jclass modifierClass = env->FindClass("java/lang/reflect/Modifier"); 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I"); 1034e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_isStatic = static_cast<bool>(callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers)); 104469a7df2e8a310b163b244af6bcc308ab29f0a1cPatrick Scott env->DeleteLocalRef(modifierClass); 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1074e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve BlockJavaMethod::~JavaMethod() 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1094e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (m_signature) 1108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block fastFree(m_signature); 1114e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block delete[] m_parameters; 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// JNI method signatures use '/' between components of a class name, but 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// we get '.' between components from the reflection API. 11676d21c39487c7753f1207935b120f3d4b06bae8dSteve Blockstatic void appendClassName(StringBuilder& builder, const char* className) 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 118a96d9eff8bdc7ed33739f5779a8d40ab1b3ae24fSteve Block#if USE(JSC) 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(JSLock::lockCount() > 0); 120a96d9eff8bdc7ed33739f5779a8d40ab1b3ae24fSteve Block#endif 1214e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 1228a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block char* c = fastStrDup(className); 1234e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 1244e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block char* result = c; 1254e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block while (*c) { 1264e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (*c == '.') 1274e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block *c = '/'; 1284e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block c++; 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1304e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 13176d21c39487c7753f1207935b120f3d4b06bae8dSteve Block builder.append(result); 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block fastFree(result); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1364e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Blockconst char* JavaMethod::signature() const 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1384e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (!m_signature) { 139a96d9eff8bdc7ed33739f5779a8d40ab1b3ae24fSteve Block#if USE(JSC) 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch JSLock lock(SilenceAssertionsOnly); 141a96d9eff8bdc7ed33739f5779a8d40ab1b3ae24fSteve Block#endif 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 14376d21c39487c7753f1207935b120f3d4b06bae8dSteve Block StringBuilder signatureBuilder; 14476d21c39487c7753f1207935b120f3d4b06bae8dSteve Block signatureBuilder.append("("); 1454e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block for (int i = 0; i < m_numParameters; i++) { 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JavaParameter* aParameter = parameterAt(i); 1474e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block JNIType type = aParameter->getJNIType(); 1484e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (type == array_type) 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendClassName(signatureBuilder, aParameter->type()); 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project else { 1514e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block signatureBuilder.append(signatureFromPrimitiveType(type)); 1524e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (type == object_type) { 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendClassName(signatureBuilder, aParameter->type()); 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project signatureBuilder.append(";"); 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project signatureBuilder.append(")"); 1594e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 1604e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block const char* returnType = m_returnType.UTF8String(); 1614e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (m_JNIReturnType == array_type) 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendClassName(signatureBuilder, returnType); 1634e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block else { 1644e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block signatureBuilder.append(signatureFromPrimitiveType(m_JNIReturnType)); 1654e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (m_JNIReturnType == object_type) { 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project appendClassName(signatureBuilder, returnType); 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project signatureBuilder.append(";"); 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1704e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 17176d21c39487c7753f1207935b120f3d4b06bae8dSteve Block String signatureString = signatureBuilder.toString(); 1728a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block m_signature = fastStrDup(signatureString.utf8().data()); 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1744e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block 1754e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block return m_signature; 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectJNIType JavaMethod::JNIReturnType() const 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1804e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block return m_JNIReturnType; 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1834e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve BlockjmethodID JavaMethod::methodID(jobject obj) const 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1854e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block if (!m_methodID) 1864e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block m_methodID = getMethodID(obj, m_name.UTF8String(), signature()); 1874e226d42cbe1a5d3bd6b7e92663df661fc14adc3Steve Block return m_methodID; 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(MAC_JAVA_BRIDGE) 191