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