Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include "jni.h"
21 : : #include "osl/security.h"
22 : : #include <osl/pipe.h>
23 : :
24 : : /* On Windows, jpipe.dll must not have dependencies on any other URE DLLs, as
25 : : Java System.LoadLibrary could otherwise not load it. Therefore, on Windows,
26 : : this code goes into a jpipx.dll that the jpipe.dll wrapper loads with
27 : : LoadLibraryEx(LOAD_WITH_ALTERED_SEARCH_PATH). The function names in this
28 : : wrapped code are truncated from the long JNICALL names, as JNICALL causes
29 : : some "@N" with different numeric values for N (and probably different across
30 : : 32 and 64 bit) to be added to the symbol names, which the calls to
31 : : GetProcAddress in wrapper/wrapper.c would otheriwse have to take into
32 : : account.
33 : : */
34 : :
35 : : /*****************************************************************************/
36 : : /* exception macros */
37 : :
38 : 662 : static void ThrowException(JNIEnv * env, char const * type, char const * msg) {
39 : : jclass c;
40 : 662 : (*env)->ExceptionClear(env);
41 : 662 : c = (*env)->FindClass(env, type);
42 [ - + ]: 662 : if (c == NULL) {
43 : 0 : (*env)->ExceptionClear(env);
44 : 0 : (*env)->FatalError(env, "JNI FindClass failed");
45 : : }
46 [ - + ]: 662 : if ((*env)->ThrowNew(env, c, msg) != 0) {
47 : 0 : (*env)->ExceptionClear(env);
48 : 0 : (*env)->FatalError(env, "JNI ThrowNew failed");
49 : : }
50 : 662 : }
51 : :
52 : : /*****************************************************************************/
53 : : /* helper functions prototypes */
54 : :
55 : : static oslPipe getPipe(JNIEnv * env, jobject obj_this);
56 : : static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr);
57 : :
58 : : /*****************************************************************************/
59 : : /* get pipe */
60 : :
61 : 7788791 : static oslPipe getPipe(JNIEnv * env, jobject obj_this)
62 : : {
63 : : jclass tclass;
64 : : jfieldID fid;
65 : 7788791 : tclass = (*env)->GetObjectClass(env, obj_this);
66 [ - + ]: 7788791 : if (tclass == NULL)
67 : : {
68 : 0 : ThrowException(env,
69 : : "java/lang/RuntimeException",
70 : : "native pipe cannot find class");
71 : 0 : return NULL;
72 : : }
73 : :
74 : 7788791 : fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
75 [ - + ]: 7788791 : if (fid == NULL)
76 : : {
77 : 0 : ThrowException(env,
78 : : "java/lang/RuntimeException",
79 : : "native pipe cannot find field");
80 : 0 : return NULL;
81 : : }
82 : 7788791 : return (oslPipe) SAL_INT_CAST(
83 : : sal_IntPtr, (*env)->GetLongField(env, obj_this, fid));
84 : : }
85 : :
86 : : /*****************************************************************************/
87 : : /* convert jstring to rtl_uString */
88 : :
89 : 756 : static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr)
90 : : {
91 : : const char * cstr;
92 : 756 : rtl_uString * ustr = NULL;
93 : 756 : cstr = (*env)->GetStringUTFChars(env, jstr, NULL);
94 : 756 : rtl_uString_newFromAscii(&ustr, cstr);
95 : 756 : (*env)->ReleaseStringUTFChars(env, jstr, cstr);
96 : 756 : return ustr;
97 : : }
98 : :
99 : : /*****************************************************************************/
100 : : /*
101 : : * Class: com_sun_star_lib_connections_pipe_PipeConnection
102 : : * Method: connect
103 : : * Signature: (Lcom/sun/star/beans/NativeService;)V
104 : : */
105 : : SAL_DLLPUBLIC_EXPORT void
106 : : #if defined WNT
107 : : PipeConnection_create
108 : : #else
109 : 756 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_createJNI
110 : : #endif
111 : : (JNIEnv * env, jobject obj_this, jstring name)
112 : : {
113 : : enum {
114 : : START = 0,
115 : : INMONITOR,
116 : : GOTNAME,
117 : : CREATED
118 : : };
119 : :
120 : 756 : short state = START;
121 : :
122 : : jclass tclass;
123 : : jfieldID fid;
124 : :
125 : 756 : oslSecurity psec = osl_getCurrentSecurity();
126 : 756 : oslPipe npipe = NULL;
127 : 756 : rtl_uString * pname = NULL;
128 [ - + ]: 756 : if ((*env)->MonitorEnter(env, obj_this) != 0)
129 : : {
130 : 0 : ThrowException(env,
131 : : "java/lang/RuntimeException",
132 : : "native pipe cannot synchronize on the object");
133 : 0 : goto error;
134 : : }
135 : 756 : state = INMONITOR;
136 : :
137 : : /* check connection state */
138 : 756 : npipe = getPipe(env, obj_this);
139 [ - + ]: 756 : if ((*env)->ExceptionOccurred(env) != NULL)
140 : 0 : goto error;
141 [ - + ]: 756 : if (npipe != NULL)
142 : : {
143 : 0 : ThrowException(env,
144 : : "com/sun/star/io/IOException",
145 : : "native pipe is already connected");
146 : 0 : goto error;
147 : : }
148 : :
149 : : /* save the pipe name */
150 : 756 : tclass = (*env)->GetObjectClass(env, obj_this);
151 [ - + ]: 756 : if (tclass == NULL)
152 : : {
153 : 0 : ThrowException(env,
154 : : "java/lang/RuntimeException",
155 : : "native pipe cannot find class");
156 : 0 : goto error;
157 : : }
158 : :
159 : 756 : fid = (*env)->GetFieldID(env, tclass,
160 : : "_aDescription", "Ljava/lang/String;");
161 [ - + ]: 756 : if (fid == NULL)
162 : : {
163 : 0 : ThrowException(env,
164 : : "java/lang/RuntimeException",
165 : : "native pipe cannot find field");
166 : 0 : goto error;
167 : : }
168 : :
169 : 756 : (*env)->SetObjectField(env, obj_this, fid, (jobject)name);
170 : :
171 : : /* convert pipe name to rtl_uString */
172 : 756 : pname = jstring2ustring(env, name);
173 [ - + ]: 756 : if (pname == NULL)
174 : : {
175 : 0 : ThrowException(env,
176 : : "java/lang/RuntimeException",
177 : : "native pipe cannot convert name");
178 : 0 : goto error;
179 : : }
180 : 756 : state = GOTNAME;
181 : :
182 : : /* try to connect */
183 : 756 : npipe = osl_createPipe(pname, osl_Pipe_OPEN, psec);
184 [ + + ]: 756 : if (npipe == NULL)
185 : : {
186 : 662 : ThrowException(env,
187 : : "java/lang/RuntimeException",
188 : : "cannot create native pipe");
189 : 662 : goto error;
190 : : }
191 : 94 : state = CREATED;
192 : :
193 : : /* save the pipe */
194 : 94 : tclass = (*env)->GetObjectClass(env, obj_this);
195 [ - + ]: 94 : if (tclass == NULL)
196 : : {
197 : 0 : ThrowException(env,
198 : : "java/lang/RuntimeException",
199 : : "native pipe cannot find class");
200 : 0 : goto error;
201 : : }
202 : :
203 : 94 : fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
204 [ - + ]: 94 : if (fid == NULL)
205 : : {
206 : 0 : ThrowException(env,
207 : : "java/lang/RuntimeException",
208 : : "native pipe cannot find field");
209 : 0 : goto error;
210 : : }
211 : 94 : (*env)->SetLongField(
212 : 94 : env, obj_this, fid, SAL_INT_CAST(jlong, (sal_IntPtr) npipe));
213 : :
214 : : /* done */
215 : 94 : rtl_uString_release(pname);
216 : 94 : (*env)->MonitorExit(env, obj_this);
217 : 94 : osl_freeSecurityHandle(psec);
218 : 94 : return;
219 : :
220 : : error:
221 [ - + - - : 662 : switch (state)
- ]
222 : : {
223 : : case CREATED:
224 : 0 : osl_closePipe(npipe);
225 : 0 : osl_releasePipe(npipe);
226 : : case GOTNAME:
227 : 662 : rtl_uString_release(pname);
228 : : case INMONITOR:
229 : 662 : (*env)->MonitorExit(env, obj_this);
230 : : case START:
231 : 662 : osl_freeSecurityHandle(psec);
232 : : default:
233 : 662 : break;
234 : : }
235 : 756 : return;
236 : : }
237 : :
238 : : /*****************************************************************************/
239 : : /*
240 : : * Class: com_sun_star_lib_connections_pipe_PipeConnection
241 : : * Method: closeJNI
242 : : * Signature: ()V
243 : : */
244 : : SAL_DLLPUBLIC_EXPORT void
245 : : #if defined WNT
246 : : PipeConnection_close
247 : : #else
248 : 94 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_closeJNI
249 : : #endif
250 : : (JNIEnv * env, jobject obj_this)
251 : : {
252 : : enum {
253 : : START = 0,
254 : : INMONITOR
255 : : };
256 : :
257 : 94 : short state = START;
258 : : oslPipe npipe; /* native pipe */
259 : : jclass tclass; /* this class */
260 : : jfieldID fid; /* a field identifier */
261 : :
262 [ - + ]: 94 : if ((*env)->MonitorEnter(env, obj_this) != 0)
263 : : {
264 : 0 : ThrowException(env,
265 : : "java/lang/RuntimeException",
266 : : "native pipe cannot synchronize on the object");
267 : 0 : goto error;
268 : : }
269 : 94 : state = INMONITOR;
270 : :
271 : : /* check connection state */
272 : 94 : npipe = getPipe(env, obj_this);
273 [ - + ]: 94 : if ((*env)->ExceptionOccurred(env) != NULL)
274 : 0 : goto error;
275 [ - + ]: 94 : if (npipe == NULL)
276 : : {
277 : 0 : ThrowException(env,
278 : : "com/sun/star/io/IOException",
279 : : "native pipe is not connected");
280 : 0 : goto error;
281 : : }
282 : :
283 : : /* remove the reference to the pipe */
284 : 94 : tclass = (*env)->GetObjectClass(env, obj_this);
285 [ - + ]: 94 : if (tclass == NULL)
286 : : {
287 : 0 : ThrowException(env,
288 : : "java/lang/RuntimeException",
289 : : "native pipe cannot find class");
290 : 0 : goto error;
291 : : }
292 : :
293 : 94 : fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
294 [ - + ]: 94 : if (fid == NULL)
295 : : {
296 : 0 : ThrowException(env,
297 : : "java/lang/RuntimeException",
298 : : "native pipe cannot find field");
299 : 0 : goto error;
300 : : }
301 : :
302 : 94 : (*env)->SetLongField(env, obj_this, fid, (jlong)0);
303 : :
304 : : /* release the pipe */
305 : 94 : osl_closePipe(npipe);
306 : 94 : osl_releasePipe(npipe);
307 : :
308 : : /* done */
309 : 94 : (*env)->MonitorExit(env, obj_this);
310 : 94 : return;
311 : :
312 : : error:
313 [ # # ]: 0 : switch (state)
314 : : {
315 : : case INMONITOR:
316 : 0 : (*env)->MonitorExit(env, obj_this);
317 : : case START:
318 : : default:
319 : 0 : break;
320 : : }
321 : 94 : return;
322 : : }
323 : :
324 : : /*****************************************************************************/
325 : : /*
326 : : * Class: com_sun_star_lib_connections_pipe_PipeConnection
327 : : * Method: readJNI
328 : : * Signature: ([[BI)I
329 : : */
330 : : SAL_DLLPUBLIC_EXPORT jint
331 : : #if defined WNT
332 : : PipeConnection_read
333 : : #else
334 : 3501448 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_readJNI
335 : : #endif
336 : : (JNIEnv * env, jobject obj_this, jobjectArray buffer, jint len)
337 : : {
338 : : enum {
339 : : START = 0,
340 : : INMONITOR,
341 : : AQUIRED,
342 : : GOTBUFFER
343 : : };
344 : :
345 : 3501448 : short state = START;
346 : : oslPipe npipe; /* native pipe */
347 : 3501448 : void * nbuff = NULL; /* native read buffer */
348 : : jbyteArray bytes; /* java read buffer */
349 : : jint nread; /* number of bytes has been read */
350 : :
351 : : /* enter monitor */
352 [ - + ]: 3501448 : if ((*env)->MonitorEnter(env, obj_this) != 0)
353 : : {
354 : 0 : ThrowException(env,
355 : : "java/lang/RuntimeException",
356 : : "native pipe cannot synchronize on the object");
357 : 0 : goto error;
358 : : }
359 : 3501448 : state = INMONITOR;
360 : :
361 : : /* check connection state */
362 : 3501448 : npipe = getPipe(env, obj_this);
363 [ - + ]: 3501448 : if ((*env)->ExceptionOccurred(env) != NULL)
364 : 0 : goto error;
365 [ - + ]: 3501448 : if (npipe == NULL)
366 : : {
367 : 0 : ThrowException(env,
368 : : "com/sun/star/io/IOException",
369 : : "native pipe is not connected");
370 : 0 : goto error;
371 : : }
372 : :
373 : : /* aquire pipe */
374 : 3501448 : osl_acquirePipe( npipe );
375 : 3501448 : state = AQUIRED;
376 : :
377 : : /* allocate a buffer */
378 [ - + ]: 3501448 : if ((nbuff = malloc(len)) == NULL)
379 : : {
380 : 0 : ThrowException(env,
381 : : "java/lang/RuntimeException",
382 : : "native pipe out of memory");
383 : 0 : goto error;
384 : : }
385 : :
386 : 3501448 : state = GOTBUFFER;
387 : :
388 : : /* exit monitor */
389 : 3501448 : (*env)->MonitorExit(env, obj_this);
390 : :
391 : : /* reading */
392 : 3501448 : nread = osl_readPipe(npipe, nbuff, len);
393 : :
394 : : /* enter monitor again */
395 [ - + ]: 3501448 : if ((*env)->MonitorEnter(env, obj_this) != 0)
396 : : {
397 : 0 : ThrowException(env,
398 : : "java/lang/RuntimeException",
399 : : "native pipe cannot synchronize on the object");
400 : 0 : goto error;
401 : : }
402 : :
403 : : /* copy buffer */
404 [ + - ]: 3501448 : if (nread >= 0)
405 : : {
406 : 3501448 : bytes = (*env)->NewByteArray(env, len);
407 [ - + ]: 3501448 : if (bytes == NULL)
408 : : {
409 : 0 : ThrowException(env,
410 : : "java/lang/RuntimeException",
411 : : "native pipe out of memory");
412 : 0 : goto error;
413 : : }
414 : :
415 : : /* save the data */
416 : 3501448 : (*env)->SetByteArrayRegion(env, bytes, 0, len, nbuff);
417 : 3501448 : (*env)->SetObjectArrayElement(env, buffer, 0, bytes);
418 : 3501448 : (*env)->DeleteLocalRef(env, bytes);
419 : : }
420 : :
421 : : /* done */
422 : 3501448 : free(nbuff);
423 [ + - ]: 3501448 : if ( state >= AQUIRED )
424 : 3501448 : osl_releasePipe( npipe );
425 : :
426 : : /* exit monitor */
427 : 3501448 : (*env)->MonitorExit(env, obj_this);
428 : 3501448 : return nread;
429 : :
430 : : error:
431 [ # # # ]: 0 : switch (state)
432 : : {
433 : : case GOTBUFFER:
434 : 0 : free(nbuff);
435 : : case INMONITOR:
436 : 0 : (*env)->MonitorExit(env, obj_this);
437 : : case START:
438 : : default:
439 : 0 : break;
440 : : }
441 : 3501448 : return -1;
442 : : }
443 : :
444 : : /*****************************************************************************/
445 : : /*
446 : : * Class: com_sun_star_lib_connections_pipe_PipeConnection
447 : : * Method: writeJNI
448 : : * Signature: ([B)V
449 : : */
450 : : SAL_DLLPUBLIC_EXPORT void
451 : : #if defined WNT
452 : : PipeConnection_write
453 : : #else
454 : 4286493 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_writeJNI
455 : : #endif
456 : : (JNIEnv * env, jobject obj_this, jbyteArray buffer)
457 : : {
458 : : enum {
459 : : START = 0,
460 : : INMONITOR,
461 : : GOTBUFFER
462 : : };
463 : :
464 : 4286493 : short state = START;
465 : : oslPipe npipe; /* native pipe */
466 : : long count; /* number of bytes has been written */
467 : : jsize nwrite; /* number of bytes to write */
468 : 4286493 : jbyte * nbuff = NULL; /* native buffer */
469 : :
470 [ - + ]: 4286493 : if ((*env)->MonitorEnter(env, obj_this) != 0)
471 : : {
472 : 0 : ThrowException(env,
473 : : "java/lang/RuntimeException",
474 : : "native pipe cannot synchronize on the object");
475 : 0 : goto error;
476 : : }
477 : 4286493 : state = INMONITOR;
478 : :
479 : : /* check connection state */
480 : 4286493 : npipe = getPipe(env, obj_this);
481 [ - + ]: 4286493 : if ((*env)->ExceptionOccurred(env) != NULL)
482 : 0 : goto error;
483 [ - + ]: 4286493 : if (npipe == NULL)
484 : : {
485 : 0 : ThrowException(env,
486 : : "com/sun/star/io/IOException",
487 : : "native pipe is not connected");
488 : 0 : goto error;
489 : : }
490 : :
491 : 4286493 : nwrite = (*env)->GetArrayLength(env, buffer);
492 [ + - ]: 4286493 : if (nwrite > 0)
493 : : {
494 : 4286493 : nbuff = (*env)->GetByteArrayElements(env, buffer, NULL);
495 [ - + ]: 4286493 : if (nbuff == NULL)
496 : : {
497 : 0 : ThrowException(env,
498 : : "java/lang/RuntimeException",
499 : : "native pipe out of memory");
500 : 0 : goto error;
501 : : }
502 : 4286493 : state = GOTBUFFER;
503 : :
504 : 4286493 : (*env)->MonitorExit(env, obj_this);
505 : : /* writing */
506 : 4286493 : count = osl_writePipe(npipe, nbuff, nwrite);
507 [ - + ]: 4286493 : if ((*env)->MonitorEnter(env, obj_this) != 0)
508 : : {
509 : 0 : ThrowException(env,
510 : : "java/lang/RuntimeException",
511 : : "native pipe cannot synchronize on the object");
512 : 0 : goto error;
513 : : }
514 [ - + ]: 4286493 : if (count != nwrite)
515 : : {
516 : 0 : ThrowException(env,
517 : : "com/sun/star/io/IOException",
518 : : "native pipe is failed to write");
519 : 0 : goto error;
520 : : }
521 : : }
522 : : /* done */
523 : 4286493 : (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
524 : 4286493 : (*env)->MonitorExit(env, obj_this);
525 : 4286493 : return;
526 : :
527 : : error:
528 [ # # # ]: 0 : switch (state)
529 : : {
530 : : case GOTBUFFER:
531 : 0 : (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
532 : : case INMONITOR:
533 : 0 : (*env)->MonitorExit(env, obj_this);
534 : : case START:
535 : : default:
536 : 0 : break;
537 : : }
538 : 4286493 : return;
539 : : }
540 : :
541 : : /*****************************************************************************/
542 : : /*
543 : : * Class: com_sun_star_lib_connections_pipe_PipeConnection
544 : : * Method: flushJNI
545 : : * Signature: ()V
546 : : */
547 : : SAL_DLLPUBLIC_EXPORT void
548 : : #if defined WNT
549 : : PipeConnection_flush
550 : : #else
551 : 380488 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_flushJNI
552 : : #endif
553 : : (JNIEnv * env, jobject obj_this)
554 : : {
555 : : (void) env; /* not used */
556 : : (void) obj_this; /* not used */
557 : 380488 : return;
558 : : }
559 : :
560 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|