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