1/* 2 * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved. 3 * Copyright 2010, The Android Open Source Project 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "JavaMethodJobject.h" 29 30#if ENABLE(JAVA_BRIDGE) 31 32#include "JavaString.h" 33 34#if USE(JSC) 35#include <runtime/JSObject.h> 36#include <runtime/ScopeChain.h> 37#endif 38#include <wtf/text/StringBuilder.h> 39 40using namespace JSC; 41using namespace JSC::Bindings; 42 43JavaMethodJobject::JavaMethodJobject(JNIEnv* env, jobject aMethod) 44{ 45 // Get return type name 46 jstring returnTypeName = 0; 47 if (jobject returnType = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;")) { 48 returnTypeName = static_cast<jstring>(callJNIMethod<jobject>(returnType, "getName", "()Ljava/lang/String;")); 49 if (!returnTypeName) 50 returnTypeName = env->NewStringUTF("<Unknown>"); 51 env->DeleteLocalRef(returnType); 52 } 53 m_returnTypeClassName = JavaString(env, returnTypeName); 54 m_returnType = javaTypeFromClassName(m_returnTypeClassName.utf8()); 55 env->DeleteLocalRef(returnTypeName); 56 57 // Get method name 58 jstring methodName = static_cast<jstring>(callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;")); 59 if (!methodName) 60 methodName = env->NewStringUTF("<Unknown>"); 61 m_name = JavaString(env, methodName); 62 env->DeleteLocalRef(methodName); 63 64 // Get parameters 65 if (jarray jparameters = static_cast<jarray>(callJNIMethod<jobject>(aMethod, "getParameterTypes", "()[Ljava/lang/Class;"))) { 66 unsigned int numParams = env->GetArrayLength(jparameters); 67 68 for (unsigned int i = 0; i < numParams; i++) { 69 jobject aParameter = env->GetObjectArrayElement(static_cast<jobjectArray>(jparameters), i); 70 jstring parameterName = static_cast<jstring>(callJNIMethod<jobject>(aParameter, "getName", "()Ljava/lang/String;")); 71 if (!parameterName) 72 parameterName = env->NewStringUTF("<Unknown>"); 73 m_parameters.append(JavaString(env, parameterName).impl()); 74 env->DeleteLocalRef(aParameter); 75 env->DeleteLocalRef(parameterName); 76 } 77 env->DeleteLocalRef(jparameters); 78 } 79 80 // Created lazily. 81 m_signature = 0; 82 83 jclass modifierClass = env->FindClass("java/lang/reflect/Modifier"); 84 int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I"); 85 m_isStatic = static_cast<bool>(callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers)); 86 env->DeleteLocalRef(modifierClass); 87} 88 89JavaMethodJobject::~JavaMethodJobject() 90{ 91 if (m_signature) 92 fastFree(m_signature); 93} 94 95// JNI method signatures use '/' between components of a class name, but 96// we get '.' between components from the reflection API. 97static void appendClassName(StringBuilder& builder, const char* className) 98{ 99#if USE(JSC) 100 ASSERT(JSLock::lockCount() > 0); 101#endif 102 103 char* c = fastStrDup(className); 104 105 char* result = c; 106 while (*c) { 107 if (*c == '.') 108 *c = '/'; 109 c++; 110 } 111 112 builder.append(result); 113 114 fastFree(result); 115} 116 117const char* JavaMethodJobject::signature() const 118{ 119 if (!m_signature) { 120#if USE(JSC) 121 JSLock lock(SilenceAssertionsOnly); 122#endif 123 124 StringBuilder signatureBuilder; 125 signatureBuilder.append('('); 126 for (unsigned int i = 0; i < m_parameters.size(); i++) { 127 CString javaClassName = parameterAt(i).utf8(); 128 JavaType type = javaTypeFromClassName(javaClassName.data()); 129 if (type == JavaTypeArray) 130 appendClassName(signatureBuilder, javaClassName.data()); 131 else { 132 signatureBuilder.append(signatureFromJavaType(type)); 133 if (type == JavaTypeObject 134// ANDROID 135 || type == JavaTypeString 136// ANDROID 137 ) { 138 appendClassName(signatureBuilder, javaClassName.data()); 139 signatureBuilder.append(';'); 140 } 141 } 142 } 143 signatureBuilder.append(')'); 144 145 const char* returnType = m_returnTypeClassName.utf8(); 146 if (m_returnType == JavaTypeArray) 147 appendClassName(signatureBuilder, returnType); 148 else { 149 signatureBuilder.append(signatureFromJavaType(m_returnType)); 150 if (m_returnType == JavaTypeObject 151// ANDROID 152 || m_returnType == JavaTypeString 153// ANDROID 154 ) { 155 appendClassName(signatureBuilder, returnType); 156 signatureBuilder.append(';'); 157 } 158 } 159 160 String signatureString = signatureBuilder.toString(); 161 m_signature = fastStrDup(signatureString.utf8().data()); 162 } 163 164 return m_signature; 165} 166 167#endif // ENABLE(JAVA_BRIDGE) 168