• 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 "JavaArrayJSC.h"
29 
30 #if ENABLE(JAVA_BRIDGE)
31 
32 #include "JNIUtilityPrivate.h"
33 #include "JavaInstanceJSC.h"
34 #include "JobjectWrapper.h"
35 #include "Logging.h"
36 #include "runtime_array.h"
37 #include "runtime_object.h"
38 #include "runtime_root.h"
39 #include <runtime/Error.h>
40 
41 using namespace JSC;
42 using namespace JSC::Bindings;
43 using namespace WebCore;
44 
convertJObjectToArray(ExecState * exec,jobject anObject,const char * type,PassRefPtr<RootObject> rootObject)45 JSValue JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
46 {
47     if (type[0] != '[')
48         return jsUndefined();
49 
50     return new (exec) RuntimeArray(exec, new JavaArray(anObject, type, rootObject));
51 }
52 
JavaArray(jobject array,const char * type,PassRefPtr<RootObject> rootObject)53 JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
54     : Array(rootObject)
55 {
56     m_array = new JobjectWrapper(array);
57     // Java array are fixed length, so we can cache length.
58     JNIEnv* env = getJNIEnv();
59     m_length = env->GetArrayLength(static_cast<jarray>(m_array->m_instance));
60     m_type = strdup(type);
61 }
62 
~JavaArray()63 JavaArray::~JavaArray()
64 {
65     free(const_cast<char*>(m_type));
66 }
67 
rootObject() const68 RootObject* JavaArray::rootObject() const
69 {
70     return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
71 }
72 
setValueAt(ExecState * exec,unsigned index,JSValue aValue) const73 void JavaArray::setValueAt(ExecState* exec, unsigned index, JSValue aValue) const
74 {
75     JNIEnv* env = getJNIEnv();
76     char* javaClassName = 0;
77 
78     JavaType arrayType = javaTypeFromPrimitiveType(m_type[1]);
79     if (m_type[1] == 'L') {
80         // The type of the array will be something like:
81         // "[Ljava.lang.string;". This is guaranteed, so no need
82         // for extra sanity checks.
83         javaClassName = strdup(&m_type[2]);
84         javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
85     }
86     jvalue aJValue = convertValueToJValue(exec, m_rootObject.get(), aValue, arrayType, javaClassName);
87 
88     switch (arrayType) {
89     case JavaTypeObject:
90         {
91             env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray()), index, aJValue.l);
92             break;
93         }
94 
95     case JavaTypeBoolean:
96         {
97             env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray()), index, 1, &aJValue.z);
98             break;
99         }
100 
101     case JavaTypeByte:
102         {
103             env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray()), index, 1, &aJValue.b);
104             break;
105         }
106 
107     case JavaTypeChar:
108         {
109             env->SetCharArrayRegion(static_cast<jcharArray>(javaArray()), index, 1, &aJValue.c);
110             break;
111         }
112 
113     case JavaTypeShort:
114         {
115             env->SetShortArrayRegion(static_cast<jshortArray>(javaArray()), index, 1, &aJValue.s);
116             break;
117         }
118 
119     case JavaTypeInt:
120         {
121             env->SetIntArrayRegion(static_cast<jintArray>(javaArray()), index, 1, &aJValue.i);
122             break;
123         }
124 
125     case JavaTypeLong:
126         {
127             env->SetLongArrayRegion(static_cast<jlongArray>(javaArray()), index, 1, &aJValue.j);
128         }
129 
130     case JavaTypeFloat:
131         {
132             env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray()), index, 1, &aJValue.f);
133             break;
134         }
135 
136     case JavaTypeDouble:
137         {
138             env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray()), index, 1, &aJValue.d);
139             break;
140         }
141     default:
142         break;
143     }
144 
145     if (javaClassName)
146         free(const_cast<char*>(javaClassName));
147 }
148 
valueAt(ExecState * exec,unsigned index) const149 JSValue JavaArray::valueAt(ExecState* exec, unsigned index) const
150 {
151     JNIEnv* env = getJNIEnv();
152     JavaType arrayType = javaTypeFromPrimitiveType(m_type[1]);
153     switch (arrayType) {
154     case JavaTypeObject:
155         {
156             jobjectArray objectArray = static_cast<jobjectArray>(javaArray());
157             jobject anObject;
158             anObject = env->GetObjectArrayElement(objectArray, index);
159 
160             // No object?
161             if (!anObject)
162                 return jsNull();
163 
164             // Nested array?
165             if (m_type[1] == '[')
166                 return JavaArray::convertJObjectToArray(exec, anObject, m_type + 1, rootObject());
167             // or array of other object type?
168             return JavaInstance::create(anObject, rootObject())->createRuntimeObject(exec);
169         }
170 
171     case JavaTypeBoolean:
172         {
173             jbooleanArray booleanArray = static_cast<jbooleanArray>(javaArray());
174             jboolean aBoolean;
175             env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
176             return jsBoolean(aBoolean);
177         }
178 
179     case JavaTypeByte:
180         {
181             jbyteArray byteArray = static_cast<jbyteArray>(javaArray());
182             jbyte aByte;
183             env->GetByteArrayRegion(byteArray, index, 1, &aByte);
184             return jsNumber(aByte);
185         }
186 
187     case JavaTypeChar:
188         {
189             jcharArray charArray = static_cast<jcharArray>(javaArray());
190             jchar aChar;
191             env->GetCharArrayRegion(charArray, index, 1, &aChar);
192             return jsNumber(aChar);
193             break;
194         }
195 
196     case JavaTypeShort:
197         {
198             jshortArray shortArray = static_cast<jshortArray>(javaArray());
199             jshort aShort;
200             env->GetShortArrayRegion(shortArray, index, 1, &aShort);
201             return jsNumber(aShort);
202         }
203 
204     case JavaTypeInt:
205         {
206             jintArray intArray = static_cast<jintArray>(javaArray());
207             jint anInt;
208             env->GetIntArrayRegion(intArray, index, 1, &anInt);
209             return jsNumber(anInt);
210         }
211 
212     case JavaTypeLong:
213         {
214             jlongArray longArray = static_cast<jlongArray>(javaArray());
215             jlong aLong;
216             env->GetLongArrayRegion(longArray, index, 1, &aLong);
217             return jsNumber(aLong);
218         }
219 
220     case JavaTypeFloat:
221         {
222             jfloatArray floatArray = static_cast<jfloatArray>(javaArray());
223             jfloat aFloat;
224             env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
225             return jsNumber(aFloat);
226         }
227 
228     case JavaTypeDouble:
229         {
230             jdoubleArray doubleArray = static_cast<jdoubleArray>(javaArray());
231             jdouble aDouble;
232             env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
233             return jsNumber(aDouble);
234         }
235     default:
236         break;
237     }
238     return jsUndefined();
239 }
240 
getLength() const241 unsigned int JavaArray::getLength() const
242 {
243     return m_length;
244 }
245 
246 #endif // ENABLE(JAVA_BRIDGE)
247