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