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 "JNIBridge.h"
29
30 #if ENABLE(MAC_JAVA_BRIDGE)
31
32 #include "CString.h"
33 #include "StringBuilder.h"
34
35
36 #ifdef NDEBUG
37 #define JS_LOG(formatAndArgs...) ((void)0)
38 #else
39 #define JS_LOG(formatAndArgs...) { \
40 fprintf(stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
41 fprintf(stderr, formatAndArgs); \
42 }
43 #endif
44
45 using namespace JSC;
46 using namespace JSC::Bindings;
47 using namespace WebCore;
48
49
JavaParameter(JNIEnv * env,jstring type)50 JavaParameter::JavaParameter(JNIEnv* env, jstring type)
51 {
52 m_type = JavaString(env, type);
53 m_JNIType = JNITypeFromClassName(m_type.UTF8String());
54 }
55
JavaMethod(JNIEnv * env,jobject aMethod)56 JavaMethod::JavaMethod(JNIEnv* env, jobject aMethod)
57 {
58 // Get return type name
59 jstring returnTypeName = 0;
60 if (jobject returnType = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;")) {
61 returnTypeName = static_cast<jstring>(callJNIMethod<jobject>(returnType, "getName", "()Ljava/lang/String;"));
62 if (!returnTypeName)
63 returnTypeName = env->NewStringUTF("<Unknown>");
64 env->DeleteLocalRef(returnType);
65 }
66 m_returnType = JavaString(env, returnTypeName);
67 m_JNIReturnType = JNITypeFromClassName(m_returnType.UTF8String());
68 env->DeleteLocalRef(returnTypeName);
69
70 // Get method name
71 jstring methodName = static_cast<jstring>(callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;"));
72 if (!returnTypeName)
73 returnTypeName = env->NewStringUTF("<Unknown>");
74 m_name = JavaString(env, methodName);
75 env->DeleteLocalRef(methodName);
76
77 // Get parameters
78 if (jarray jparameters = static_cast<jarray>(callJNIMethod<jobject>(aMethod, "getParameterTypes", "()[Ljava/lang/Class;"))) {
79 m_numParameters = env->GetArrayLength(jparameters);
80 m_parameters = new JavaParameter[m_numParameters];
81
82 for (int i = 0; i < m_numParameters; i++) {
83 jobject aParameter = env->GetObjectArrayElement(static_cast<jobjectArray>(jparameters), i);
84 jstring parameterName = static_cast<jstring>(callJNIMethod<jobject>(aParameter, "getName", "()Ljava/lang/String;"));
85 if (!parameterName)
86 parameterName = env->NewStringUTF("<Unknown>");
87 m_parameters[i] = JavaParameter(env, parameterName);
88 env->DeleteLocalRef(aParameter);
89 env->DeleteLocalRef(parameterName);
90 }
91 env->DeleteLocalRef(jparameters);
92 } else {
93 m_numParameters = 0;
94 m_parameters = 0;
95 }
96
97 // Created lazily.
98 m_signature = 0;
99 m_methodID = 0;
100
101 jclass modifierClass = env->FindClass("java/lang/reflect/Modifier");
102 int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I");
103 m_isStatic = static_cast<bool>(callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers));
104 env->DeleteLocalRef(modifierClass);
105 }
106
~JavaMethod()107 JavaMethod::~JavaMethod()
108 {
109 if (m_signature)
110 fastFree(m_signature);
111 delete[] m_parameters;
112 };
113
114 // JNI method signatures use '/' between components of a class name, but
115 // we get '.' between components from the reflection API.
appendClassName(StringBuilder & builder,const char * className)116 static void appendClassName(StringBuilder& builder, const char* className)
117 {
118 #if USE(JSC)
119 ASSERT(JSLock::lockCount() > 0);
120 #endif
121
122 char* c = fastStrDup(className);
123
124 char* result = c;
125 while (*c) {
126 if (*c == '.')
127 *c = '/';
128 c++;
129 }
130
131 builder.append(result);
132
133 fastFree(result);
134 }
135
signature() const136 const char* JavaMethod::signature() const
137 {
138 if (!m_signature) {
139 #if USE(JSC)
140 JSLock lock(SilenceAssertionsOnly);
141 #endif
142
143 StringBuilder signatureBuilder;
144 signatureBuilder.append("(");
145 for (int i = 0; i < m_numParameters; i++) {
146 JavaParameter* aParameter = parameterAt(i);
147 JNIType type = aParameter->getJNIType();
148 if (type == array_type)
149 appendClassName(signatureBuilder, aParameter->type());
150 else {
151 signatureBuilder.append(signatureFromPrimitiveType(type));
152 if (type == object_type) {
153 appendClassName(signatureBuilder, aParameter->type());
154 signatureBuilder.append(";");
155 }
156 }
157 }
158 signatureBuilder.append(")");
159
160 const char* returnType = m_returnType.UTF8String();
161 if (m_JNIReturnType == array_type)
162 appendClassName(signatureBuilder, returnType);
163 else {
164 signatureBuilder.append(signatureFromPrimitiveType(m_JNIReturnType));
165 if (m_JNIReturnType == object_type) {
166 appendClassName(signatureBuilder, returnType);
167 signatureBuilder.append(";");
168 }
169 }
170
171 String signatureString = signatureBuilder.toString();
172 m_signature = fastStrDup(signatureString.utf8().data());
173 }
174
175 return m_signature;
176 }
177
JNIReturnType() const178 JNIType JavaMethod::JNIReturnType() const
179 {
180 return m_JNIReturnType;
181 }
182
methodID(jobject obj) const183 jmethodID JavaMethod::methodID(jobject obj) const
184 {
185 if (!m_methodID)
186 m_methodID = getMethodID(obj, m_name.UTF8String(), signature());
187 return m_methodID;
188 }
189
190 #endif // ENABLE(MAC_JAVA_BRIDGE)
191