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 329 : static void ThrowException(JNIEnv * env, char const * type, char const * msg) {
39 : jclass c;
40 329 : (*env)->ExceptionClear(env);
41 329 : c = (*env)->FindClass(env, type);
42 329 : if (c == NULL) {
43 0 : (*env)->ExceptionClear(env);
44 0 : (*env)->FatalError(env, "JNI FindClass failed");
45 : }
46 329 : if ((*env)->ThrowNew(env, c, msg) != 0) {
47 0 : (*env)->ExceptionClear(env);
48 0 : (*env)->FatalError(env, "JNI ThrowNew failed");
49 : }
50 329 : }
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 4177322 : static oslPipe getPipe(JNIEnv * env, jobject obj_this)
62 : {
63 : jclass tclass;
64 : jfieldID fid;
65 4177322 : tclass = (*env)->GetObjectClass(env, obj_this);
66 4177322 : 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 4177322 : fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
75 4177322 : if (fid == NULL)
76 : {
77 0 : ThrowException(env,
78 : "java/lang/RuntimeException",
79 : "native pipe cannot find field");
80 0 : return NULL;
81 : }
82 4177322 : 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 376 : static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr)
90 : {
91 : const char * cstr;
92 376 : rtl_uString * ustr = NULL;
93 376 : cstr = (*env)->GetStringUTFChars(env, jstr, NULL);
94 376 : rtl_uString_newFromAscii(&ustr, cstr);
95 376 : (*env)->ReleaseStringUTFChars(env, jstr, cstr);
96 376 : 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 376 : 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 376 : short state = START;
121 :
122 : jclass tclass;
123 : jfieldID fid;
124 :
125 376 : oslSecurity psec = osl_getCurrentSecurity();
126 376 : oslPipe npipe = NULL;
127 376 : rtl_uString * pname = NULL;
128 376 : 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 376 : state = INMONITOR;
136 :
137 : /* check connection state */
138 376 : npipe = getPipe(env, obj_this);
139 376 : if ((*env)->ExceptionOccurred(env) != NULL)
140 0 : goto error;
141 376 : 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 376 : tclass = (*env)->GetObjectClass(env, obj_this);
151 376 : 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 376 : fid = (*env)->GetFieldID(env, tclass,
160 : "_aDescription", "Ljava/lang/String;");
161 376 : 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 376 : (*env)->SetObjectField(env, obj_this, fid, (jobject)name);
170 :
171 : /* convert pipe name to rtl_uString */
172 376 : pname = jstring2ustring(env, name);
173 376 : if (pname == NULL)
174 : {
175 0 : ThrowException(env,
176 : "java/lang/RuntimeException",
177 : "native pipe cannot convert name");
178 0 : goto error;
179 : }
180 376 : state = GOTNAME;
181 :
182 : /* try to connect */
183 376 : npipe = osl_createPipe(pname, osl_Pipe_OPEN, psec);
184 376 : if (npipe == NULL)
185 : {
186 329 : ThrowException(env,
187 : "java/lang/RuntimeException",
188 : "cannot create native pipe");
189 329 : goto error;
190 : }
191 47 : state = CREATED;
192 :
193 : /* save the pipe */
194 47 : tclass = (*env)->GetObjectClass(env, obj_this);
195 47 : 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 47 : fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
204 47 : 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 47 : env, obj_this, fid, SAL_INT_CAST(jlong, (sal_IntPtr) npipe));
213 :
214 : /* done */
215 47 : rtl_uString_release(pname);
216 47 : (*env)->MonitorExit(env, obj_this);
217 47 : osl_freeSecurityHandle(psec);
218 47 : return;
219 :
220 : error:
221 329 : switch (state)
222 : {
223 : case CREATED:
224 0 : osl_closePipe(npipe);
225 0 : osl_releasePipe(npipe);
226 : case GOTNAME:
227 329 : rtl_uString_release(pname);
228 : case INMONITOR:
229 329 : (*env)->MonitorExit(env, obj_this);
230 : case START:
231 329 : osl_freeSecurityHandle(psec);
232 : default:
233 329 : break;
234 : }
235 329 : 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 47 : 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 47 : short state = START;
258 : oslPipe npipe; /* native pipe */
259 : jclass tclass; /* this class */
260 : jfieldID fid; /* a field identifier */
261 :
262 47 : 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 47 : state = INMONITOR;
270 :
271 : /* check connection state */
272 47 : npipe = getPipe(env, obj_this);
273 47 : if ((*env)->ExceptionOccurred(env) != NULL)
274 0 : goto error;
275 47 : 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 47 : tclass = (*env)->GetObjectClass(env, obj_this);
285 47 : 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 47 : fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
294 47 : 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 47 : (*env)->SetLongField(env, obj_this, fid, (jlong)0);
303 :
304 : /* release the pipe */
305 47 : osl_closePipe(npipe);
306 47 : osl_releasePipe(npipe);
307 :
308 : /* done */
309 47 : (*env)->MonitorExit(env, obj_this);
310 47 : 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 0 : 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 1864997 : 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 1864997 : short state = START;
346 : oslPipe npipe; /* native pipe */
347 1864997 : 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 1864997 : 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 1864997 : state = INMONITOR;
360 :
361 : /* check connection state */
362 1864997 : npipe = getPipe(env, obj_this);
363 1864997 : if ((*env)->ExceptionOccurred(env) != NULL)
364 0 : goto error;
365 1864997 : 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 1864997 : osl_acquirePipe( npipe );
375 1864997 : state = AQUIRED;
376 :
377 : /* allocate a buffer */
378 1864997 : 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 1864997 : state = GOTBUFFER;
387 :
388 : /* exit monitor */
389 1864997 : (*env)->MonitorExit(env, obj_this);
390 :
391 : /* reading */
392 1864997 : nread = osl_readPipe(npipe, nbuff, len);
393 :
394 : /* enter monitor again */
395 1864997 : 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 1864997 : if (nread >= 0)
405 : {
406 1864997 : bytes = (*env)->NewByteArray(env, len);
407 1864997 : 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 1864997 : (*env)->SetByteArrayRegion(env, bytes, 0, len, nbuff);
417 1864997 : (*env)->SetObjectArrayElement(env, buffer, 0, bytes);
418 1864997 : (*env)->DeleteLocalRef(env, bytes);
419 : }
420 :
421 : /* done */
422 1864997 : free(nbuff);
423 1864997 : if ( state >= AQUIRED )
424 1864997 : osl_releasePipe( npipe );
425 :
426 : /* exit monitor */
427 1864997 : (*env)->MonitorExit(env, obj_this);
428 1864997 : 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 0 : 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 2311902 : 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 2311902 : 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 2311902 : jbyte * nbuff = NULL; /* native buffer */
469 :
470 2311902 : 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 2311902 : state = INMONITOR;
478 :
479 : /* check connection state */
480 2311902 : npipe = getPipe(env, obj_this);
481 2311902 : if ((*env)->ExceptionOccurred(env) != NULL)
482 0 : goto error;
483 2311902 : 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 2311902 : nwrite = (*env)->GetArrayLength(env, buffer);
492 2311902 : if (nwrite > 0)
493 : {
494 2311902 : nbuff = (*env)->GetByteArrayElements(env, buffer, NULL);
495 2311902 : if (nbuff == NULL)
496 : {
497 0 : ThrowException(env,
498 : "java/lang/RuntimeException",
499 : "native pipe out of memory");
500 0 : goto error;
501 : }
502 2311902 : state = GOTBUFFER;
503 :
504 2311902 : (*env)->MonitorExit(env, obj_this);
505 : /* writing */
506 2311902 : count = osl_writePipe(npipe, nbuff, nwrite);
507 2311902 : 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 2311902 : if (count != nwrite)
515 : {
516 0 : ThrowException(env,
517 : "com/sun/star/io/IOException",
518 : "native pipe: failed to write");
519 0 : goto error;
520 : }
521 : }
522 : /* done */
523 2311902 : (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
524 2311902 : (*env)->MonitorExit(env, obj_this);
525 2311902 : 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 0 : 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 202772 : 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 202772 : return;
558 : }
559 :
560 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|