• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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