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 40 using namespace JSC; 41 using namespace JSC::Bindings; 42 43 JavaMethodJobject::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 89 JavaMethodJobject::~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. 97 static 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 117 const 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