Bump version to 6.4-15
[LibreOffice.git] / jurt / source / pipe / com_sun_star_lib_connections_pipe_PipeConnection.c
blob9b7806b8a07a20dfbf0a704d097f0a8b46376266
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <stdlib.h>
24 #include <jni.h>
25 #include <osl/security.h>
26 #include <osl/pipe.h>
28 /* On Windows, jpipe.dll must not have static dependencies on any other URE DLLs
29 (sal3.dll, uwinapi.dll), as Java System.LoadLibrary could otherwise not load
30 it. Therefore, on Windows, this code goes into a jpipx.dll that the jpipe.dll
31 wrapper loads with LoadLibraryEx(LOAD_WITH_ALTERED_SEARCH_PATH).
32 The function names in this wrapped code are truncated from the long JNICALL
33 names, as JNICALL causes some "@N" with different numeric values for
34 N (and probably different across 32 and 64 bit) to be added to the symbol
35 names, which the calls to GetProcAddress in wrapper/wrapper.c would otherwise
36 have to take into account.
39 /*****************************************************************************/
40 /* exception macros */
42 static void ThrowException(JNIEnv * env, char const * type, char const * msg) {
43 jclass c;
44 (*env)->ExceptionClear(env);
45 c = (*env)->FindClass(env, type);
46 if (c == NULL) {
47 (*env)->ExceptionClear(env);
48 (*env)->FatalError(env, "JNI FindClass failed");
50 if ((*env)->ThrowNew(env, c, msg) != 0) {
51 (*env)->ExceptionClear(env);
52 (*env)->FatalError(env, "JNI ThrowNew failed");
56 /*****************************************************************************/
57 /* helper functions prototypes */
59 static oslPipe getPipe(JNIEnv * env, jobject obj_this);
60 static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr);
62 /*****************************************************************************/
63 /* get pipe */
65 static oslPipe getPipe(JNIEnv * env, jobject obj_this)
67 jclass tclass;
68 jfieldID fid;
69 tclass = (*env)->GetObjectClass(env, obj_this);
70 if (tclass == NULL)
72 ThrowException(env,
73 "java/lang/RuntimeException",
74 "native pipe cannot find class");
75 return NULL;
78 fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
79 if (fid == NULL)
81 ThrowException(env,
82 "java/lang/RuntimeException",
83 "native pipe cannot find field");
84 return NULL;
86 return (oslPipe) SAL_INT_CAST(
87 sal_IntPtr, (*env)->GetLongField(env, obj_this, fid));
90 /*****************************************************************************/
91 /* convert jstring to rtl_uString */
93 static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr)
95 const char * cstr;
96 rtl_uString * ustr = NULL;
97 cstr = (*env)->GetStringUTFChars(env, jstr, NULL);
98 rtl_uString_newFromAscii(&ustr, cstr);
99 (*env)->ReleaseStringUTFChars(env, jstr, cstr);
100 return ustr;
103 /*****************************************************************************/
105 * Class: com_sun_star_lib_connections_pipe_PipeConnection
106 * Method: connect
107 * Signature: (Lcom/sun/star/beans/NativeService;)V
109 SAL_DLLPUBLIC_EXPORT void
110 #if defined(_WIN32)
111 PipeConnection_create
112 #else
113 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_createJNI
114 #endif
115 (JNIEnv * env, jobject obj_this, jstring name)
117 enum {
118 START = 0,
119 INMONITOR,
120 GOTNAME,
121 CREATED
124 short state = START;
126 jclass tclass;
127 jfieldID fid;
129 oslSecurity psec = osl_getCurrentSecurity();
130 oslPipe npipe = NULL;
131 rtl_uString * pname = NULL;
132 if ((*env)->MonitorEnter(env, obj_this) != 0)
134 ThrowException(env,
135 "java/lang/RuntimeException",
136 "native pipe cannot synchronize on the object");
137 goto error;
139 state = INMONITOR;
141 /* check connection state */
142 npipe = getPipe(env, obj_this);
143 if ((*env)->ExceptionOccurred(env) != NULL)
144 goto error;
145 if (npipe != NULL)
147 ThrowException(env,
148 "com/sun/star/io/IOException",
149 "native pipe is already connected");
150 goto error;
153 /* save the pipe name */
154 tclass = (*env)->GetObjectClass(env, obj_this);
155 if (tclass == NULL)
157 ThrowException(env,
158 "java/lang/RuntimeException",
159 "native pipe cannot find class");
160 goto error;
163 fid = (*env)->GetFieldID(env, tclass,
164 "_aDescription", "Ljava/lang/String;");
165 if (fid == NULL)
167 ThrowException(env,
168 "java/lang/RuntimeException",
169 "native pipe cannot find field");
170 goto error;
173 (*env)->SetObjectField(env, obj_this, fid, (jobject)name);
175 /* convert pipe name to rtl_uString */
176 pname = jstring2ustring(env, name);
177 if (pname == NULL)
179 ThrowException(env,
180 "java/lang/RuntimeException",
181 "native pipe cannot convert name");
182 goto error;
184 state = GOTNAME;
186 /* try to connect */
187 npipe = osl_createPipe(pname, osl_Pipe_OPEN, psec);
188 if (npipe == NULL)
190 ThrowException(env,
191 "java/lang/RuntimeException",
192 "cannot create native pipe");
193 goto error;
195 state = CREATED;
197 /* save the pipe */
198 tclass = (*env)->GetObjectClass(env, obj_this);
199 if (tclass == NULL)
201 ThrowException(env,
202 "java/lang/RuntimeException",
203 "native pipe cannot find class");
204 goto error;
207 fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
208 if (fid == NULL)
210 ThrowException(env,
211 "java/lang/RuntimeException",
212 "native pipe cannot find field");
213 goto error;
215 (*env)->SetLongField(
216 env, obj_this, fid, SAL_INT_CAST(jlong, (sal_IntPtr) npipe));
218 /* done */
219 rtl_uString_release(pname);
220 (*env)->MonitorExit(env, obj_this);
221 osl_freeSecurityHandle(psec);
222 return;
224 error:
225 switch (state)
227 case CREATED:
228 osl_closePipe(npipe);
229 osl_releasePipe(npipe);
230 /* fall through */
231 case GOTNAME:
232 rtl_uString_release(pname);
233 /* fall through */
234 case INMONITOR:
235 (*env)->MonitorExit(env, obj_this);
236 /* fall through */
237 case START:
238 osl_freeSecurityHandle(psec);
239 default:
240 break;
242 return;
245 /*****************************************************************************/
247 * Class: com_sun_star_lib_connections_pipe_PipeConnection
248 * Method: closeJNI
249 * Signature: ()V
251 SAL_DLLPUBLIC_EXPORT void
252 #if defined(_WIN32)
253 PipeConnection_close
254 #else
255 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_closeJNI
256 #endif
257 (JNIEnv * env, jobject obj_this)
259 enum {
260 START = 0,
261 INMONITOR,
262 GOTPIPE,
265 short state = START;
266 oslPipe npipe = NULL; /* native pipe */
267 jclass tclass; /* this class */
268 jfieldID fid; /* a field identifier */
270 if ((*env)->MonitorEnter(env, obj_this) != 0)
272 ThrowException(env,
273 "java/lang/RuntimeException",
274 "native pipe cannot synchronize on the object");
275 goto cleanup;
277 state = INMONITOR;
279 /* check connection state */
280 npipe = getPipe(env, obj_this);
281 if ((*env)->ExceptionOccurred(env) != NULL)
282 goto cleanup;
283 if (npipe == NULL)
285 ThrowException(env,
286 "com/sun/star/io/IOException",
287 "native pipe is not connected");
288 goto cleanup;
290 state = GOTPIPE;
292 /* remove the reference to the pipe */
293 tclass = (*env)->GetObjectClass(env, obj_this);
294 if (tclass == NULL)
296 ThrowException(env,
297 "java/lang/RuntimeException",
298 "native pipe cannot find class");
299 goto cleanup;
302 fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
303 if (fid == NULL)
305 ThrowException(env,
306 "java/lang/RuntimeException",
307 "native pipe cannot find field");
308 goto cleanup;
311 (*env)->SetLongField(env, obj_this, fid, (jlong)0);
313 /* done */
315 cleanup:
316 switch (state)
318 case GOTPIPE:
319 /* release the pipe */
320 osl_closePipe(npipe);
321 osl_releasePipe(npipe);
322 /* fall-through */
323 case INMONITOR:
324 (*env)->MonitorExit(env, obj_this);
325 /* fall-through */
326 case START:
327 default:
328 break;
330 return;
333 /*****************************************************************************/
335 * Class: com_sun_star_lib_connections_pipe_PipeConnection
336 * Method: readJNI
337 * Signature: ([[BI)I
339 SAL_DLLPUBLIC_EXPORT jint
340 #if defined(_WIN32)
341 PipeConnection_read
342 #else
343 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_readJNI
344 #endif
345 (JNIEnv * env, jobject obj_this, jobjectArray buffer, jint len)
347 enum {
348 START = 0,
349 INMONITOR,
350 ACQUIRED,
351 GOTBUFFER
354 short state = START;
355 oslPipe npipe = NULL; /* native pipe */
356 void * nbuff = NULL; /* native read buffer */
357 jbyteArray bytes; /* java read buffer */
358 jint nread; /* number of bytes has been read */
359 jint nreturn = -1; /* actual return value */
361 /* enter monitor */
362 if ((*env)->MonitorEnter(env, obj_this) != 0)
364 ThrowException(env,
365 "java/lang/RuntimeException",
366 "native pipe cannot synchronize on the object");
367 goto cleanup;
369 state = INMONITOR;
371 /* check connection state */
372 npipe = getPipe(env, obj_this);
373 if ((*env)->ExceptionOccurred(env) != NULL)
374 goto cleanup;
375 if (npipe == NULL)
377 ThrowException(env,
378 "com/sun/star/io/IOException",
379 "native pipe is not connected");
380 goto cleanup;
383 /* acquire pipe */
384 osl_acquirePipe( npipe );
385 state = ACQUIRED;
387 /* allocate a buffer */
388 if ((nbuff = malloc(len)) == NULL)
390 ThrowException(env,
391 "java/lang/RuntimeException",
392 "native pipe out of memory");
393 goto cleanup;
396 state = GOTBUFFER;
398 /* exit monitor */
399 (*env)->MonitorExit(env, obj_this);
401 /* reading */
402 nread = osl_readPipe(npipe, nbuff, len);
404 /* enter monitor again */
405 if ((*env)->MonitorEnter(env, obj_this) != 0)
407 ThrowException(env,
408 "java/lang/RuntimeException",
409 "native pipe cannot synchronize on the object");
410 goto cleanup;
413 /* copy buffer */
414 if (nread >= 0)
416 bytes = (*env)->NewByteArray(env, len);
417 if (bytes == NULL)
419 ThrowException(env,
420 "java/lang/RuntimeException",
421 "native pipe out of memory");
422 goto cleanup;
425 /* save the data */
426 (*env)->SetByteArrayRegion(env, bytes, 0, len, nbuff);
427 (*env)->SetObjectArrayElement(env, buffer, 0, bytes);
428 (*env)->DeleteLocalRef(env, bytes);
431 /* done */
432 nreturn = nread;
434 cleanup:
435 switch (state)
437 case GOTBUFFER:
438 free(nbuff);
439 /* fall-through */
440 case ACQUIRED:
441 osl_releasePipe(npipe);
442 /* fall-through */
443 case INMONITOR:
444 (*env)->MonitorExit(env, obj_this);
445 /* fall-through */
446 case START:
447 default:
448 break;
450 return nreturn;
453 /*****************************************************************************/
455 * Class: com_sun_star_lib_connections_pipe_PipeConnection
456 * Method: writeJNI
457 * Signature: ([B)V
459 SAL_DLLPUBLIC_EXPORT void
460 #if defined(_WIN32)
461 PipeConnection_write
462 #else
463 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_writeJNI
464 #endif
465 (JNIEnv * env, jobject obj_this, jbyteArray buffer)
467 enum {
468 START = 0,
469 INMONITOR,
470 GOTBUFFER
473 short state = START;
474 oslPipe npipe; /* native pipe */
475 sal_Int32 count; /* number of bytes has been written */
476 jsize nwrite; /* number of bytes to write */
477 jbyte * nbuff = NULL; /* native buffer */
479 if ((*env)->MonitorEnter(env, obj_this) != 0)
481 ThrowException(env,
482 "java/lang/RuntimeException",
483 "native pipe cannot synchronize on the object");
484 goto cleanup;
486 state = INMONITOR;
488 /* check connection state */
489 npipe = getPipe(env, obj_this);
490 if ((*env)->ExceptionOccurred(env) != NULL)
491 goto cleanup;
492 if (npipe == NULL)
494 ThrowException(env,
495 "com/sun/star/io/IOException",
496 "native pipe is not connected");
497 goto cleanup;
500 nwrite = (*env)->GetArrayLength(env, buffer);
501 if (nwrite > 0)
503 nbuff = (*env)->GetByteArrayElements(env, buffer, NULL);
504 if (nbuff == NULL)
506 ThrowException(env,
507 "java/lang/RuntimeException",
508 "native pipe out of memory");
509 goto cleanup;
511 state = GOTBUFFER;
513 (*env)->MonitorExit(env, obj_this);
514 /* writing */
515 count = osl_writePipe(npipe, nbuff, nwrite);
516 if ((*env)->MonitorEnter(env, obj_this) != 0)
518 ThrowException(env,
519 "java/lang/RuntimeException",
520 "native pipe cannot synchronize on the object");
521 goto cleanup;
523 if (count != nwrite)
525 ThrowException(env,
526 "com/sun/star/io/IOException",
527 "native pipe: failed to write");
528 goto cleanup;
531 /* done */
533 cleanup:
534 switch (state)
536 case GOTBUFFER:
537 (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
538 /* fall through */
539 case INMONITOR:
540 (*env)->MonitorExit(env, obj_this);
541 /* fall through */
542 case START:
543 default:
544 break;
546 return;
549 /*****************************************************************************/
551 * Class: com_sun_star_lib_connections_pipe_PipeConnection
552 * Method: flushJNI
553 * Signature: ()V
555 SAL_DLLPUBLIC_EXPORT void
556 #if defined(_WIN32)
557 PipeConnection_flush
558 #else
559 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_flushJNI
560 #endif
561 (JNIEnv * env, jobject obj_this)
563 (void) env; /* not used */
564 (void) obj_this; /* not used */
565 return;
568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */