LCOV - code coverage report
Current view: top level - jurt/source/pipe - com_sun_star_lib_connections_pipe_PipeConnection.c (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 120 190 63.2 %
Date: 2015-06-13 12:38:46 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          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 static dependencies on any other URE DLLs
      25             :    (sal3.dll, uwinapi.dll), as Java System.LoadLibrary could otherwise not load
      26             :    it.  Therefore, on Windows, this code goes into a jpipx.dll that the jpipe.dll
      27             :    wrapper loads with LoadLibraryEx(LOAD_WITH_ALTERED_SEARCH_PATH).
      28             :    The function names in this wrapped code are truncated from the long JNICALL
      29             :    names, as JNICALL causes some "@N" with different numeric values for
      30             :    N (and probably different across 32 and 64 bit) to be added to the symbol
      31             :    names, which the calls to GetProcAddress in wrapper/wrapper.c would otherwise
      32             :    have to take into account.
      33             : */
      34             : 
      35             : /*****************************************************************************/
      36             : /* exception macros */
      37             : 
      38         258 : static void ThrowException(JNIEnv * env, char const * type, char const * msg) {
      39             :     jclass c;
      40         258 :     (*env)->ExceptionClear(env);
      41         258 :     c = (*env)->FindClass(env, type);
      42         258 :     if (c == NULL) {
      43           0 :         (*env)->ExceptionClear(env);
      44           0 :         (*env)->FatalError(env, "JNI FindClass failed");
      45             :     }
      46         258 :     if ((*env)->ThrowNew(env, c, msg) != 0) {
      47           0 :         (*env)->ExceptionClear(env);
      48           0 :         (*env)->FatalError(env, "JNI ThrowNew failed");
      49             :     }
      50         258 : }
      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     4557326 : static oslPipe getPipe(JNIEnv * env, jobject obj_this)
      62             : {
      63             :     jclass      tclass;
      64             :     jfieldID    fid;
      65     4557326 :     tclass  = (*env)->GetObjectClass(env, obj_this);
      66     4557326 :     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     4557326 :     fid     = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
      75     4557326 :     if (fid == NULL)
      76             :     {
      77           0 :         ThrowException(env,
      78             :                        "java/lang/RuntimeException",
      79             :                        "native pipe cannot find field");
      80           0 :         return NULL;
      81             :     }
      82     4557326 :     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         327 : static rtl_uString * jstring2ustring(JNIEnv * env, jstring jstr)
      90             : {
      91             :     const char *    cstr;
      92         327 :     rtl_uString *   ustr    = NULL;
      93         327 :     cstr    = (*env)->GetStringUTFChars(env, jstr, NULL);
      94         327 :     rtl_uString_newFromAscii(&ustr, cstr);
      95         327 :     (*env)->ReleaseStringUTFChars(env, jstr, cstr);
      96         327 :     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         327 : 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         327 :     short       state   = START;
     121             : 
     122             :     jclass      tclass;
     123             :     jfieldID    fid;
     124             : 
     125         327 :     oslSecurity     psec    = osl_getCurrentSecurity();
     126         327 :     oslPipe         npipe   = NULL;
     127         327 :     rtl_uString *   pname   = NULL;
     128         327 :     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         327 :     state   = INMONITOR;
     136             : 
     137             :     /* check connection state */
     138         327 :     npipe   = getPipe(env, obj_this);
     139         327 :     if ((*env)->ExceptionOccurred(env) != NULL)
     140           0 :         goto error;
     141         327 :     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         327 :     tclass  = (*env)->GetObjectClass(env, obj_this);
     151         327 :     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         327 :     fid     = (*env)->GetFieldID(env, tclass,
     160             :                                  "_aDescription", "Ljava/lang/String;");
     161         327 :     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         327 :     (*env)->SetObjectField(env, obj_this, fid, (jobject)name);
     170             : 
     171             :     /* convert pipe name to rtl_uString */
     172         327 :     pname   = jstring2ustring(env, name);
     173         327 :     if (pname == NULL)
     174             :     {
     175           0 :         ThrowException(env,
     176             :                        "java/lang/RuntimeException",
     177             :                        "native pipe cannot convert name");
     178           0 :         goto error;
     179             :     }
     180         327 :     state   = GOTNAME;
     181             : 
     182             :     /* try to connect */
     183         327 :     npipe   = osl_createPipe(pname, osl_Pipe_OPEN, psec);
     184         327 :     if (npipe == NULL)
     185             :     {
     186         258 :         ThrowException(env,
     187             :                        "java/lang/RuntimeException",
     188             :                        "cannot create native pipe");
     189         258 :         goto error;
     190             :     }
     191          69 :     state   = CREATED;
     192             : 
     193             :     /* save the pipe */
     194          69 :     tclass  = (*env)->GetObjectClass(env, obj_this);
     195          69 :     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          69 :     fid     = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
     204          69 :     if (fid == NULL)
     205             :     {
     206           0 :         ThrowException(env,
     207             :                        "java/lang/RuntimeException",
     208             :                        "native pipe cannot find field");
     209           0 :         goto error;
     210             :     }
     211          69 :     (*env)->SetLongField(
     212             :         env, obj_this, fid, SAL_INT_CAST(jlong, (sal_IntPtr) npipe));
     213             : 
     214             :     /* done */
     215          69 :     rtl_uString_release(pname);
     216          69 :     (*env)->MonitorExit(env, obj_this);
     217          69 :     osl_freeSecurityHandle(psec);
     218          69 :     return;
     219             : 
     220             :  error:
     221         258 :     switch (state)
     222             :     {
     223             :         case CREATED:
     224           0 :             osl_closePipe(npipe);
     225           0 :             osl_releasePipe(npipe);
     226             :         case GOTNAME:
     227         258 :             rtl_uString_release(pname);
     228             :         case INMONITOR:
     229         258 :             (*env)->MonitorExit(env, obj_this);
     230             :         case START:
     231         258 :             osl_freeSecurityHandle(psec);
     232             :         default:
     233         258 :             break;
     234             :     }
     235         258 :     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          62 : 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          62 :     short       state   = START;
     258             :     oslPipe     npipe;      /* native pipe */
     259             :     jclass      tclass;     /* this class */
     260             :     jfieldID    fid;        /* a field identifier */
     261             : 
     262          62 :     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          62 :     state   = INMONITOR;
     270             : 
     271             :     /* check connection state */
     272          62 :     npipe   = getPipe(env, obj_this);
     273          62 :     if ((*env)->ExceptionOccurred(env) != NULL)
     274           0 :         goto error;
     275          62 :     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          62 :     tclass  = (*env)->GetObjectClass(env, obj_this);
     285          62 :     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          62 :     fid     = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J");
     294          62 :     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          62 :     (*env)->SetLongField(env, obj_this, fid, (jlong)0);
     303             : 
     304             :     /* release the pipe */
     305          62 :     osl_closePipe(npipe);
     306          62 :     osl_releasePipe(npipe);
     307             : 
     308             :     /* done */
     309          62 :     (*env)->MonitorExit(env, obj_this);
     310          62 :     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     2055585 : 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             :         ACQUIRED,
     342             :         GOTBUFFER
     343             :     };
     344             : 
     345     2055585 :     short       state   = START;
     346             :     oslPipe     npipe;          /* native pipe */
     347     2055585 :     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     2055585 :     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     2055585 :     state = INMONITOR;
     360             : 
     361             :     /* check connection state */
     362     2055585 :     npipe   = getPipe(env, obj_this);
     363     2055585 :     if ((*env)->ExceptionOccurred(env) != NULL)
     364           0 :         goto error;
     365     2055585 :     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             :     /* acquire pipe */
     374     2055585 :     osl_acquirePipe( npipe );
     375     2055585 :     state = ACQUIRED;
     376             : 
     377             :     /* allocate a buffer */
     378     2055585 :     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     2055585 :     state = GOTBUFFER;
     387             : 
     388             :     /* exit monitor */
     389     2055585 :     (*env)->MonitorExit(env, obj_this);
     390             : 
     391             :     /* reading */
     392     2055585 :     nread = osl_readPipe(npipe, nbuff, len);
     393             : 
     394             :     /* enter monitor again */
     395     2055583 :     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     2055578 :     if (nread >= 0)
     405             :     {
     406     2055578 :         bytes   = (*env)->NewByteArray(env, len);
     407     2055578 :         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     2055578 :         (*env)->SetByteArrayRegion(env, bytes, 0, len, nbuff);
     417     2055578 :         (*env)->SetObjectArrayElement(env, buffer, 0, bytes);
     418     2055578 :         (*env)->DeleteLocalRef(env, bytes);
     419             :     }
     420             : 
     421             :     /* done */
     422     2055578 :     free(nbuff);
     423     2055578 :     if ( state >= ACQUIRED )
     424     2055578 :         osl_releasePipe( npipe );
     425             : 
     426             :     /* exit monitor */
     427     2055578 :     (*env)->MonitorExit(env, obj_this);
     428     2055578 :     return nread;
     429             : 
     430             :  error:
     431           0 :     switch (state)
     432             :     {
     433             :         case GOTBUFFER:
     434           0 :             free(nbuff);
     435             :             /* fall-through */
     436             :         case INMONITOR:
     437           0 :             (*env)->MonitorExit(env, obj_this);
     438             :         case START:
     439             :         default:
     440           0 :             break;
     441             :     }
     442           0 :     return -1;
     443             : }
     444             : 
     445             : /*****************************************************************************/
     446             : /*
     447             :  * Class:     com_sun_star_lib_connections_pipe_PipeConnection
     448             :  * Method:    writeJNI
     449             :  * Signature: ([B)V
     450             :  */
     451             : SAL_DLLPUBLIC_EXPORT void
     452             : #if defined WNT
     453             : PipeConnection_write
     454             : #else
     455     2501352 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_writeJNI
     456             : #endif
     457             :   (JNIEnv * env, jobject obj_this, jbyteArray buffer)
     458             : {
     459             :     enum {
     460             :         START   = 0,
     461             :         INMONITOR,
     462             :         GOTBUFFER
     463             :     };
     464             : 
     465     2501352 :     short   state   = START;
     466             :     oslPipe npipe;          /* native pipe */
     467             :     long    count;          /* number of bytes has been written */
     468             :     jsize   nwrite;         /* number of bytes to write */
     469     2501352 :     jbyte * nbuff = NULL;   /* native buffer */
     470             : 
     471     2501352 :     if ((*env)->MonitorEnter(env, obj_this) != 0)
     472             :     {
     473           0 :         ThrowException(env,
     474             :                        "java/lang/RuntimeException",
     475             :                        "native pipe cannot synchronize on the object");
     476           0 :         goto error;
     477             :     }
     478     2501352 :     state   = INMONITOR;
     479             : 
     480             :     /* check connection state */
     481     2501352 :     npipe   = getPipe(env, obj_this);
     482     2501352 :     if ((*env)->ExceptionOccurred(env) != NULL)
     483           0 :         goto error;
     484     2501352 :     if (npipe == NULL)
     485             :     {
     486           0 :         ThrowException(env,
     487             :                        "com/sun/star/io/IOException",
     488             :                        "native pipe is not connected");
     489           0 :         goto error;
     490             :     }
     491             : 
     492     2501352 :     nwrite  = (*env)->GetArrayLength(env, buffer);
     493     2501352 :     if (nwrite > 0)
     494             :     {
     495     2501352 :         nbuff   = (*env)->GetByteArrayElements(env, buffer, NULL);
     496     2501352 :         if (nbuff == NULL)
     497             :         {
     498           0 :             ThrowException(env,
     499             :                            "java/lang/RuntimeException",
     500             :                            "native pipe out of memory");
     501           0 :             goto error;
     502             :         }
     503     2501352 :         state   = GOTBUFFER;
     504             : 
     505     2501352 :         (*env)->MonitorExit(env, obj_this);
     506             :         /* writing */
     507     2501352 :         count   = osl_writePipe(npipe, nbuff, nwrite);
     508     2501352 :         if ((*env)->MonitorEnter(env, obj_this) != 0)
     509             :         {
     510           0 :             ThrowException(env,
     511             :                            "java/lang/RuntimeException",
     512             :                            "native pipe cannot synchronize on the object");
     513           0 :             goto error;
     514             :         }
     515     2501352 :         if (count != nwrite)
     516             :         {
     517           0 :             ThrowException(env,
     518             :                            "com/sun/star/io/IOException",
     519             :                            "native pipe: failed to write");
     520           0 :             goto error;
     521             :         }
     522             :     }
     523             :     /* done */
     524     2501352 :     (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
     525     2501352 :     (*env)->MonitorExit(env, obj_this);
     526     2501352 :     return;
     527             : 
     528             :  error:
     529           0 :     switch (state)
     530             :     {
     531             :         case GOTBUFFER:
     532           0 :             (*env)->ReleaseByteArrayElements(env, buffer, nbuff, JNI_ABORT);
     533             :         case INMONITOR:
     534           0 :             (*env)->MonitorExit(env, obj_this);
     535             :         case START:
     536             :         default:
     537           0 :             break;
     538             :     }
     539           0 :     return;
     540             : }
     541             : 
     542             : /*****************************************************************************/
     543             : /*
     544             :  * Class:     com_sun_star_lib_connections_pipe_PipeConnection
     545             :  * Method:    flushJNI
     546             :  * Signature: ()V
     547             :  */
     548             : SAL_DLLPUBLIC_EXPORT void
     549             : #if defined WNT
     550             : PipeConnection_flush
     551             : #else
     552      223837 : JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_flushJNI
     553             : #endif
     554             :   (JNIEnv * env, jobject obj_this)
     555             : {
     556             :     (void) env; /* not used */
     557             :     (void) obj_this; /* not used */
     558      223837 :     return;
     559             : }
     560             : 
     561             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11