tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / jurt / source / pipe / com_sun_star_lib_connections_pipe_PipeConnection.c
blob58e6185614f23471ec31c70ed6f336c71c286c3c
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 #if defined __clang__
25 #pragma clang diagnostic push
26 #pragma clang diagnostic ignored "-Wunknown-attributes"
27 #endif
28 #include <jni.h>
29 #if defined __clang__
30 #pragma clang diagnostic pop
31 #endif
33 #include <osl/security.h>
34 #include <osl/pipe.h>
36 /* On Windows, jpipe.dll must not have static dependencies on any other URE DLLs
37 (sal3.dll, uwinapi.dll), as Java System.LoadLibrary could otherwise not load
38 it. Therefore, on Windows, this code goes into a jpipx.dll that the jpipe.dll
39 wrapper loads with LoadLibraryEx(LOAD_WITH_ALTERED_SEARCH_PATH).
40 The function names in this wrapped code are truncated from the long JNICALL
41 names, as JNICALL causes some "@N" with different numeric values for
42 N (and probably different across 32 and 64 bit) to be added to the symbol
43 names, which the calls to GetProcAddress in wrapper/wrapper.c would otherwise
44 have to take into account.
47 /*****************************************************************************/
48 /* exception macros */
50 static void ThrowException(JNIEnv * env, char const * type, char const * msg) {
51 jclass c;
52 (*env)->ExceptionClear(env);
53 c = (*env)->FindClass(env, type);
54 if (c == NULL) {
55 (*env)->ExceptionClear(env);
56 (*env)->FatalError(env, "JNI FindClass failed");
58 if ((*env)->ThrowNew(env, c, msg) != 0) {
59 (*env)->ExceptionClear(env);
60 (*env)->FatalError(env, "JNI ThrowNew failed");
64 /*****************************************************************************/
65 /* helper functions prototypes */
67 static oslPipe getPipe(JNIEnv * env, jobject obj_this);
68 static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr);
70 /*****************************************************************************/
71 /* get pipe */
73 static oslPipe getPipe(JNIEnv * env, jobject obj_this)
75 jclass tclass;
76 jfieldID fid;
77 tclass = (*env)->GetObjectClass(env, obj_this);
78 if (tclass == NULL)
80 ThrowException(env,
81 "java/lang/RuntimeException",
82 "native pipe cannot find class");
83 return NULL;
86 fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
87 if (fid == NULL)
89 ThrowException(env,
90 "java/lang/RuntimeException",
91 "native pipe cannot find field");
92 return NULL;
94 return (oslPipe) SAL_INT_CAST(
95 sal_IntPtr, (*env)->GetLongField(env, obj_this, fid));
98 /*****************************************************************************/
99 /* convert jstring to rtl_uString */
101 static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr)
103 const char * cstr;
104 rtl_uString * ustr = NULL;
105 cstr = (*env)->GetStringUTFChars(env, jstr, NULL);
106 rtl_uString_newFromAscii(&ustr, cstr);
107 (*env)->ReleaseStringUTFChars(env, jstr, cstr);
108 return ustr;
111 /*****************************************************************************/
113 * Class: com_sun_star_lib_connections_pipe_PipeConnection
114 * Method: connect
115 * Signature: (Lcom/sun/star/beans/NativeService;)V
117 SAL_DLLPUBLIC_EXPORT void
118 #if defined(_WIN32)
119 PipeConnection_create
120 #else
121 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_createJNI
122 #endif
123 (JNIEnv * env, jobject obj_this, jstring name)
125 enum {
126 START = 0,
127 INMONITOR,
128 GOTNAME,
129 CREATED
132 short state = START;
134 jclass tclass;
135 jfieldID fid;
137 oslSecurity psec = osl_getCurrentSecurity();
138 oslPipe npipe = NULL;
139 rtl_uString * pname = NULL;
140 if ((*env)->MonitorEnter(env, obj_this) != 0)
142 ThrowException(env,
143 "java/lang/RuntimeException",
144 "native pipe cannot synchronize on the object");
145 goto error;
147 state = INMONITOR;
149 /* check connection state */
150 npipe = getPipe(env, obj_this);
151 if ((*env)->ExceptionOccurred(env) != NULL)
152 goto error;
153 if (npipe != NULL)
155 ThrowException(env,
156 "com/sun/star/io/IOException",
157 "native pipe is already connected");
158 goto error;
161 /* save the pipe name */
162 tclass = (*env)->GetObjectClass(env, obj_this);
163 if (tclass == NULL)
165 ThrowException(env,
166 "java/lang/RuntimeException",
167 "native pipe cannot find class");
168 goto error;
171 fid = (*env)->GetFieldID(env, tclass,
172 "_aDescription", "Ljava/lang/String;");
173 if (fid == NULL)
175 ThrowException(env,
176 "java/lang/RuntimeException",
177 "native pipe cannot find field");
178 goto error;
181 (*env)->SetObjectField(env, obj_this, fid, (jobject)name);
183 /* convert pipe name to rtl_uString */
184 pname = jstring2ustring(env, name);
185 if (pname == NULL)
187 ThrowException(env,
188 "java/lang/RuntimeException",
189 "native pipe cannot convert name");
190 goto error;
192 state = GOTNAME;
194 /* try to connect */
195 npipe = osl_createPipe(pname, osl_Pipe_OPEN, psec);
196 if (npipe == NULL)
198 ThrowException(env,
199 "java/lang/RuntimeException",
200 "cannot create native pipe");
201 goto error;
203 state = CREATED;
205 /* save the pipe */
206 tclass = (*env)->GetObjectClass(env, obj_this);
207 if (tclass == NULL)
209 ThrowException(env,
210 "java/lang/RuntimeException",
211 "native pipe cannot find class");
212 goto error;
215 fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
216 if (fid == NULL)
218 ThrowException(env,
219 "java/lang/RuntimeException",
220 "native pipe cannot find field");
221 goto error;
223 (*env)->SetLongField(
224 env, obj_this, fid, SAL_INT_CAST(jlong, (sal_IntPtr) npipe));
226 /* done */
227 rtl_uString_release(pname);
228 (*env)->MonitorExit(env, obj_this);
229 osl_freeSecurityHandle(psec);
230 return;
232 error:
233 switch (state)
235 case CREATED:
236 osl_closePipe(npipe);
237 osl_releasePipe(npipe);
238 /* fall through */
239 case GOTNAME:
240 rtl_uString_release(pname);
241 /* fall through */
242 case INMONITOR:
243 (*env)->MonitorExit(env, obj_this);
244 /* fall through */
245 case START:
246 osl_freeSecurityHandle(psec);
247 default:
248 break;
250 return;
253 /*****************************************************************************/
255 * Class: com_sun_star_lib_connections_pipe_PipeConnection
256 * Method: closeJNI
257 * Signature: ()V
259 SAL_DLLPUBLIC_EXPORT void
260 #if defined(_WIN32)
261 PipeConnection_close
262 #else
263 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_closeJNI
264 #endif
265 (JNIEnv * env, jobject obj_this)
267 enum {
268 START = 0,
269 INMONITOR,
270 GOTPIPE,
273 short state = START;
274 oslPipe npipe = NULL; /* native pipe */
275 jclass tclass; /* this class */
276 jfieldID fid; /* a field identifier */
278 if ((*env)->MonitorEnter(env, obj_this) != 0)
280 ThrowException(env,
281 "java/lang/RuntimeException",
282 "native pipe cannot synchronize on the object");
283 goto cleanup;
285 state = INMONITOR;
287 /* check connection state */
288 npipe = getPipe(env, obj_this);
289 if ((*env)->ExceptionOccurred(env) != NULL)
290 goto cleanup;
291 if (npipe == NULL)
293 ThrowException(env,
294 "com/sun/star/io/IOException",
295 "native pipe is not connected");
296 goto cleanup;
298 state = GOTPIPE;
300 /* remove the reference to the pipe */
301 tclass = (*env)->GetObjectClass(env, obj_this);
302 if (tclass == NULL)
304 ThrowException(env,
305 "java/lang/RuntimeException",
306 "native pipe cannot find class");
307 goto cleanup;
310 fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
311 if (fid == NULL)
313 ThrowException(env,
314 "java/lang/RuntimeException",
315 "native pipe cannot find field");
316 goto cleanup;
319 (*env)->SetLongField(env, obj_this, fid, (jlong)0);
321 /* done */
323 cleanup:
324 switch (state)
326 case GOTPIPE:
327 /* release the pipe */
328 osl_closePipe(npipe);
329 osl_releasePipe(npipe);
330 /* fall-through */
331 case INMONITOR:
332 (*env)->MonitorExit(env, obj_this);
333 /* fall-through */
334 case START:
335 default:
336 break;
338 return;
341 /*****************************************************************************/
343 * Class: com_sun_star_lib_connections_pipe_PipeConnection
344 * Method: readJNI
345 * Signature: ([[BI)I
347 SAL_DLLPUBLIC_EXPORT jint
348 #if defined(_WIN32)
349 PipeConnection_read
350 #else
351 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_readJNI
352 #endif
353 (JNIEnv * env, jobject obj_this, jobjectArray buffer, jint len)
355 enum {
356 START = 0,
357 INMONITOR,
358 ACQUIRED,
359 GOTBUFFER
362 short state = START;
363 oslPipe npipe = NULL; /* native pipe */
364 void * nbuff = NULL; /* native read buffer */
365 jbyteArray bytes; /* java read buffer */
366 jint nread; /* number of bytes has been read */
367 jint nreturn = -1; /* actual return value */
369 /* enter monitor */
370 if ((*env)->MonitorEnter(env, obj_this) != 0)
372 ThrowException(env,
373 "java/lang/RuntimeException",
374 "native pipe cannot synchronize on the object");
375 goto cleanup;
377 state = INMONITOR;
379 /* check connection state */
380 npipe = getPipe(env, obj_this);
381 if ((*env)->ExceptionOccurred(env) != NULL)
382 goto cleanup;
383 if (npipe == NULL)
385 ThrowException(env,
386 "com/sun/star/io/IOException",
387 "native pipe is not connected");
388 goto cleanup;
391 /* acquire pipe */
392 osl_acquirePipe( npipe );
393 state = ACQUIRED;
395 /* allocate a buffer */
396 if ((nbuff = malloc(len)) == NULL)
398 ThrowException(env,
399 "java/lang/RuntimeException",
400 "native pipe out of memory");
401 goto cleanup;
404 state = GOTBUFFER;
406 /* exit monitor */
407 (*env)->MonitorExit(env, obj_this);
409 /* reading */
410 nread = osl_readPipe(npipe, nbuff, len);
412 /* enter monitor again */
413 if ((*env)->MonitorEnter(env, obj_this) != 0)
415 ThrowException(env,
416 "java/lang/RuntimeException",
417 "native pipe cannot synchronize on the object");
418 goto cleanup;
421 /* copy buffer */
422 if (nread >= 0)
424 bytes = (*env)->NewByteArray(env, len);
425 if (bytes == NULL)
427 ThrowException(env,
428 "java/lang/RuntimeException",
429 "native pipe out of memory");
430 goto cleanup;
433 /* save the data */
434 (*env)->SetByteArrayRegion(env, bytes, 0, len, nbuff);
435 (*env)->SetObjectArrayElement(env, buffer, 0, bytes);
436 (*env)->DeleteLocalRef(env, bytes);
439 /* done */
440 nreturn = nread;
442 cleanup:
443 switch (state)
445 case GOTBUFFER:
446 free(nbuff);
447 /* fall-through */
448 case ACQUIRED:
449 osl_releasePipe(npipe);
450 /* fall-through */
451 case INMONITOR:
452 (*env)->MonitorExit(env, obj_this);
453 /* fall-through */
454 case START:
455 default:
456 break;
458 return nreturn;
461 /*****************************************************************************/
463 * Class: com_sun_star_lib_connections_pipe_PipeConnection
464 * Method: writeJNI
465 * Signature: ([B)V
467 SAL_DLLPUBLIC_EXPORT void
468 #if defined(_WIN32)
469 PipeConnection_write
470 #else
471 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_writeJNI
472 #endif
473 (JNIEnv * env, jobject obj_this, jbyteArray buffer)
475 enum {
476 START = 0,
477 INMONITOR,
478 GOTBUFFER
481 short state = START;
482 oslPipe npipe; /* native pipe */
483 sal_Int32 count; /* number of bytes has been written */
484 jsize nwrite; /* number of bytes to write */
485 jbyte * nbuff = NULL; /* native buffer */
487 if ((*env)->MonitorEnter(env, obj_this) != 0)
489 ThrowException(env,
490 "java/lang/RuntimeException",
491 "native pipe cannot synchronize on the object");
492 goto cleanup;
494 state = INMONITOR;
496 /* check connection state */
497 npipe = getPipe(env, obj_this);
498 if ((*env)->ExceptionOccurred(env) != NULL)
499 goto cleanup;
500 if (npipe == NULL)
502 ThrowException(env,
503 "com/sun/star/io/IOException",
504 "native pipe is not connected");
505 goto cleanup;
508 nwrite = (*env)->GetArrayLength(env, buffer);
509 if (nwrite > 0)
511 nbuff = (*env)->GetByteArrayElements(env, buffer, NULL);
512 if (nbuff == NULL)
514 ThrowException(env,
515 "java/lang/RuntimeException",
516 "native pipe out of memory");
517 goto cleanup;
519 state = GOTBUFFER;
521 (*env)->MonitorExit(env, obj_this);
522 /* writing */
523 count = osl_writePipe(npipe, nbuff, nwrite);
524 if ((*env)->MonitorEnter(env, obj_this) != 0)
526 ThrowException(env,
527 "java/lang/RuntimeException",
528 "native pipe cannot synchronize on the object");
529 goto cleanup;
531 if (count != nwrite)
533 ThrowException(env,
534 "com/sun/star/io/IOException",
535 "native pipe: failed to write");
536 goto cleanup;
539 /* done */
541 cleanup:
542 switch (state)
544 case GOTBUFFER:
545 (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
546 /* fall through */
547 case INMONITOR:
548 (*env)->MonitorExit(env, obj_this);
549 /* fall through */
550 case START:
551 default:
552 break;
554 return;
557 /*****************************************************************************/
559 * Class: com_sun_star_lib_connections_pipe_PipeConnection
560 * Method: flushJNI
561 * Signature: ()V
563 SAL_DLLPUBLIC_EXPORT void
564 #if defined(_WIN32)
565 PipeConnection_flush
566 #else
567 JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_flushJNI
568 #endif
569 (JNIEnv * env, jobject obj_this)
571 (void) env; /* not used */
572 (void) obj_this; /* not used */
573 return;
576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */