Reviewed by Sam.
[WebKit-https.git] / WebCore / bridge / jni / jni_class.cpp
1 /*
2  * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 #include "config.h"
26 #include "jni_class.h"
27
28 #include <kjs/identifier.h>
29 #include "jni_utility.h"
30 #include "jni_runtime.h"
31
32 using namespace KJS::Bindings;
33
34 JavaClass::JavaClass(jobject anInstance)
35 {
36     jobject aClass = callJNIObjectMethod(anInstance, "getClass", "()Ljava/lang/Class;");
37     
38     if (!aClass) {
39         fprintf(stderr, "%s:  unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance);
40         return;
41     }
42     
43     jstring className = (jstring)callJNIObjectMethod(aClass, "getName", "()Ljava/lang/String;");
44     const char *classNameC = getCharactersFromJString(className);
45     _name = strdup(classNameC);
46     releaseCharactersForJString(className, classNameC);
47
48     int i;
49     JNIEnv *env = getJNIEnv();
50     
51     // Get the fields
52     jarray fields = (jarray)callJNIObjectMethod(aClass, "getFields", "()[Ljava/lang/reflect/Field;");
53     int numFields = env->GetArrayLength(fields);    
54     for (i = 0; i < numFields; i++) {
55         jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i);
56         Field *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor
57         {
58             JSLock lock;
59             _fields.set(Identifier(aField->name()).ustring().rep(), aField);
60         }
61         env->DeleteLocalRef(aJField);
62     }
63     
64     // Get the methods
65     jarray methods = (jarray)callJNIObjectMethod(aClass, "getMethods", "()[Ljava/lang/reflect/Method;");
66     int numMethods = env->GetArrayLength(methods);
67     for (i = 0; i < numMethods; i++) {
68         jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i);
69         Method *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor
70         MethodList* methodList;
71         {
72             JSLock lock;
73
74             methodList = _methods.get(Identifier(aMethod->name()).ustring().rep());
75             if (!methodList) {
76                 methodList = new MethodList();
77                 _methods.set(Identifier(aMethod->name()).ustring().rep(), methodList);
78             }
79         }
80         methodList->append(aMethod);
81         env->DeleteLocalRef(aJMethod);
82     }    
83 }
84
85 JavaClass::~JavaClass() {
86     free((void *)_name);
87
88     JSLock lock;
89
90     deleteAllValues(_fields);
91     _fields.clear();
92
93     MethodListMap::const_iterator end = _methods.end();
94     for (MethodListMap::const_iterator it = _methods.begin(); it != end; ++it) {
95         const MethodList* methodList = it->second;
96         deleteAllValues(*methodList);
97         delete methodList;
98     }
99     _methods.clear();
100 }
101
102 MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const
103 {
104     MethodList *methodList = _methods.get(identifier.ustring().rep());
105     
106     if (methodList)
107         return *methodList;
108     return MethodList();
109 }
110
111 Field *JavaClass::fieldNamed(const Identifier& identifier, Instance*) const
112 {
113     return _fields.get(identifier.ustring().rep());
114 }
115
116 bool JavaClass::isNumberClass() const
117 {
118     return ((strcmp(_name, "java.lang.Byte") == 0 ||
119              strcmp(_name, "java.lang.Short") == 0 ||
120              strcmp(_name, "java.lang.Integer") == 0 ||
121              strcmp(_name, "java.lang.Long") == 0 ||
122              strcmp(_name, "java.lang.Float") == 0 ||
123              strcmp(_name, "java.lang.Double") == 0) );
124 }
125
126 bool JavaClass::isBooleanClass() const
127 {
128     return strcmp(_name, "java.lang.Boolean") == 0;
129 }
130
131 bool JavaClass::isStringClass() const
132 {
133     return strcmp(_name, "java.lang.String") == 0;
134 }