1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_bridges.hxx" 30 31 #include "jvmaccess/virtualmachine.hxx" 32 #include "rtl/byteseq.h" 33 #include "rtl/byteseq.hxx" 34 #include "rtl/memory.h" 35 #include "rtl/ref.hxx" 36 #include "sal/types.h" 37 #include "uno/threadpool.h" 38 39 #include "jni.h" 40 41 #include <new> 42 43 /* The native implementation part of 44 * jurt/com/sun/star/lib/uno/environments/remote/NativeThreadPool.java. 45 */ 46 47 namespace { 48 49 struct Pool { 50 Pool(rtl::Reference< jvmaccess::VirtualMachine > const & theVirtualMachine, 51 jmethodID theExecute, uno_ThreadPool thePool): 52 virtualMachine(theVirtualMachine), execute(theExecute), pool(thePool) {} 53 54 rtl::Reference< jvmaccess::VirtualMachine > virtualMachine; 55 jmethodID execute; 56 uno_ThreadPool pool; 57 }; 58 59 struct Job { 60 Job(Pool * thePool, jobject theJob): pool(thePool), job(theJob) {} 61 62 Pool * pool; 63 jobject job; 64 }; 65 66 void throwOutOfMemory(JNIEnv * env) { 67 jclass c = env->FindClass("java/lang/OutOfMemoryError"); 68 if (c != 0) { 69 env->ThrowNew(c, ""); 70 } 71 } 72 73 } 74 75 extern "C" { 76 77 static void SAL_CALL executeRequest(void * data) { 78 Job * job = static_cast< Job * >(data); 79 try { 80 jvmaccess::VirtualMachine::AttachGuard guard(job->pool->virtualMachine); 81 JNIEnv * env = guard.getEnvironment(); 82 // Failure of the following Job.execute Java call is ignored; if that 83 // call fails, it should be due to a java.lang.Error, which is not 84 // handled well, anyway: 85 env->CallObjectMethod(job->job, job->pool->execute); 86 env->DeleteGlobalRef(job->job); 87 delete job; 88 } catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) { 89 //TODO: DeleteGlobalRef(job->job) 90 delete job; 91 } 92 } 93 94 } 95 96 extern "C" JNIEXPORT jbyteArray JNICALL 97 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_threadId( 98 JNIEnv * env, jclass) SAL_THROW_EXTERN_C() 99 { 100 sal_Sequence * s = 0; 101 uno_getIdOfCurrentThread(&s); //TODO: out of memory 102 uno_releaseIdFromCurrentThread(); 103 rtl::ByteSequence seq(s); 104 rtl_byte_sequence_release(s); 105 sal_Int32 n = seq.getLength(); 106 jbyteArray a = env->NewByteArray(n); 107 // sal_Int32 and jsize are compatible here 108 if (a == 0) { 109 return 0; 110 } 111 void * p = env->GetPrimitiveArrayCritical(a, 0); 112 if (p == 0) { 113 return 0; 114 } 115 rtl_copyMemory(p, seq.getConstArray(), n); 116 // sal_Int8 and jbyte ought to be compatible 117 env->ReleasePrimitiveArrayCritical(a, p, 0); 118 return a; 119 } 120 121 extern "C" JNIEXPORT jlong JNICALL 122 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_create( 123 JNIEnv * env, jclass) SAL_THROW_EXTERN_C() 124 { 125 JavaVM * vm; 126 if (env->GetJavaVM(&vm) != JNI_OK) { //TODO: no Java exception raised? 127 jclass c = env->FindClass("java/lang/RuntimeException"); 128 if (c != 0) { 129 env->ThrowNew(c, "JNI GetJavaVM failed"); 130 } 131 return 0; 132 } 133 jclass c = env->FindClass("com/sun/star/lib/uno/environments/remote/Job"); 134 if (c == 0) { 135 return 0; 136 } 137 jmethodID execute = env->GetMethodID(c, "execute", "()Ljava/lang/Object;"); 138 if (execute == 0) { 139 return 0; 140 } 141 try { 142 return reinterpret_cast< jlong >(new Pool( 143 new jvmaccess::VirtualMachine(vm, env->GetVersion(), false, env), 144 execute, uno_threadpool_create())); 145 } catch (std::bad_alloc) { 146 throwOutOfMemory(env); 147 return 0; 148 } 149 } 150 151 extern "C" JNIEXPORT void JNICALL 152 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_attach( 153 JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() 154 { 155 uno_threadpool_attach(reinterpret_cast< Pool * >(pool)->pool); 156 } 157 158 extern "C" JNIEXPORT jobject JNICALL 159 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_enter( 160 JNIEnv * env, jclass, jlong pool) SAL_THROW_EXTERN_C() 161 { 162 jobject job; 163 uno_threadpool_enter( 164 reinterpret_cast< Pool * >(pool)->pool, 165 reinterpret_cast< void ** >(&job)); 166 if (job == 0) { 167 return 0; 168 } 169 jobject ref = env->NewLocalRef(job); 170 env->DeleteGlobalRef(job); 171 return ref; 172 } 173 174 extern "C" JNIEXPORT void JNICALL 175 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_detach( 176 JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() 177 { 178 uno_threadpool_detach(reinterpret_cast< Pool * >(pool)->pool); 179 } 180 181 extern "C" JNIEXPORT void JNICALL 182 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_putJob( 183 JNIEnv * env, jclass, jlong pool, jbyteArray threadId, jobject job, 184 jboolean request, jboolean oneWay) SAL_THROW_EXTERN_C() 185 { 186 void * s = env->GetPrimitiveArrayCritical(threadId, 0); 187 if (s == 0) { 188 return; 189 } 190 rtl::ByteSequence seq( 191 static_cast< sal_Int8 * >(s), env->GetArrayLength(threadId)); 192 // sal_Int8 and jbyte ought to be compatible; sal_Int32 and jsize are 193 // compatible here 194 //TODO: out of memory 195 env->ReleasePrimitiveArrayCritical(threadId, s, JNI_ABORT); 196 Pool * p = reinterpret_cast< Pool * >(pool); 197 jobject ref = env->NewGlobalRef(job); 198 if (ref == 0) { 199 return; 200 } 201 Job * j = 0; 202 if (request) { 203 j = new(std::nothrow) Job(p, ref); 204 if (j == 0) { 205 env->DeleteGlobalRef(ref); 206 throwOutOfMemory(env); 207 return; 208 } 209 } 210 uno_threadpool_putJob( 211 p->pool, seq.getHandle(), 212 request ? static_cast< void * >(j) : static_cast< void * >(ref), 213 request ? executeRequest : 0, oneWay); 214 } 215 216 extern "C" JNIEXPORT void JNICALL 217 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_dispose( 218 JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() 219 { 220 uno_threadpool_dispose(reinterpret_cast< Pool * >(pool)->pool); 221 } 222 223 extern "C" JNIEXPORT void JNICALL 224 Java_com_sun_star_lib_uno_environments_remote_NativeThreadPool_destroy( 225 JNIEnv *, jclass, jlong pool) SAL_THROW_EXTERN_C() 226 { 227 Pool * p = reinterpret_cast< Pool * >(pool); 228 uno_threadpool_destroy(p->pool); 229 delete p; 230 } 231