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 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 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 63 JavaArray::~JavaArray() 64 { 65 free(const_cast<char*>(m_type)); 66 } 67 68 RootObject* JavaArray::rootObject() const 69 { 70 return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0; 71 } 72 73 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 149 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 241 unsigned int JavaArray::getLength() const 242 { 243 return m_length; 244 } 245 246 #endif // ENABLE(JAVA_BRIDGE) 247