]> rtime.felk.cvut.cz Git - orte.git/blob - orte/libjorte/JORTESubscriptionCreate.c
improved JAVA interface from Lukas, update makefiles from msvc from Jan
[orte.git] / orte / libjorte / JORTESubscriptionCreate.c
1 /* JORTESubscriptionCreate.c  */
2
3 /**
4   * This code provides conversion between JAVA a C environments.
5   * The C functions are calling here and results are send to JAVA
6   * native functions. It uses the header pregenerated by JAVA
7   * (by command 'javah -jni class_with_native_function')
8   *
9   * @author Lukas Pokorny (lukas_pokorny@centrum.cz)
10   * @author CTU FEE Prague - Department of Control Engineering (dce.felk.cvut.cz)
11   * @author Project ORTE - OCERA Real Time Ethernet (www.ocera.org)
12   * @author dedication to Kj
13   * @version 0.1
14   *
15   *
16   * This program is free software; you can redistribute it and/or modify
17   * it under the terms of the GNU General Public License as published by
18   * the Free Software Foundation; either version 2 of the License, or
19   * (at your option) any later version.
20   *
21   * This program is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24   * GNU General Public License for more details.
25   *
26   */
27
28
29 #include <stdlib.h>
30
31 // library header file's path
32 #include "orte.h"
33 // pregenerated header
34 #include "jorte/org_ocera_orte_Subscription.h"
35 // enable TEST_STAGE run level
36 #include "jorte/4all.h"
37 // new data types
38 #include "jorte/jorte_typedefs_defines.h"
39 #include "jorte/jorte_protos_api.h"
40
41 /* ****************************************************************** *
42  *                           CallBack function                        *
43  * ****************************************************************** */
44
45 void
46 recvCallBack(const ORTERecvInfo *info,void *vinstance, void *recvCallBackParam)
47 {
48   // jni varialbles
49   JavaVM          *jvm = 0;
50   JNIEnv          *env = 0;
51   jclass           cls = 0; // local reference!
52   jclass           cls_msg = 0;
53   jclass           cls_bb;
54   jclass           cls_tmp = 0;
55   jobject          obj = 0;
56   jobject          rinfo = 0;
57   jobject          obj_msg;
58   jobject          obj_bb;
59   jmethodID        mid = 0;
60   jmethodID        mid_callback = 0;
61   jfieldID         fid = 0;
62   //
63   char            *buffer;
64   int              i;
65   int              buff_length;
66   int              flag_ok = 0;
67   //
68   JORTECallbackContext_t   *callback_cont = (JORTECallbackContext_t*)recvCallBackParam;
69
70   #ifdef TEST_STAGE
71     printf("\n\n:c: --------------- recvCallBack called.. --------------- \n");
72   #endif
73
74   do
75   {
76     // set local variables from struct
77     if(callback_cont->jvm == 0)
78     {
79       #ifdef TEST_STAGE
80         printf(":!c: jvm = NULL \n");
81       #endif
82       break;
83     }
84     jvm = callback_cont->jvm;
85     // get env
86     (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
87     if(env == 0)
88     {
89       #ifdef TEST_STAGE
90        printf(":!c: env = NULL \n");
91       #endif
92       break;
93     }
94     //
95     if(callback_cont->obj == 0)
96     {
97       #ifdef TEST_STAGE
98         printf(":!c: obj = NULL \n");
99       #endif
100       break;
101     }
102     // set local vars
103     obj = callback_cont->obj;
104     rinfo = callback_cont->rinfo;
105     obj_msg = callback_cont->msg;
106     obj_bb = callback_cont->bbuff;
107
108
109       #ifdef TEST_STAGE
110          printf(":c: #0 \n");
111          printf(":c: env = %p, obj_msg = %p \n", env, obj_msg);
112       #endif
113
114
115         //
116     if(rinfo == 0)
117     {
118       // find cls
119       cls = (*env)->FindClass(env, "org/ocera/orte/types/RecvInfo");
120       if(cls == 0)
121       {
122         #ifdef TEST_STAGE
123           printf(":!c: cls = NULL \n");
124         #endif
125         break;
126       }
127       // call object constructor
128       mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
129       if(mid == 0)
130       {
131         #ifdef TEST_STAGE
132           printf(":!c: constructor failed! \n");
133         #endif
134         break;
135       }
136       // create new object
137       rinfo = (*env)->NewObject(env, cls, mid);
138       if(rinfo == 0)
139       {
140         #ifdef TEST_STAGE
141           printf(":!c: rinfo = NULL \n");
142         #endif
143         break;
144       }
145       // create global reference
146       callback_cont->rinfo = (*env)->NewGlobalRef(env, rinfo);
147       if (callback_cont->rinfo == 0)
148       {
149         #ifdef TEST_STAGE
150           printf(":!c: callback_cont->rinfo = NULL \n");
151         #endif
152         break;
153       }
154     }
155     ////////////////////////////////////////////////////
156     // set RecvInfo instance
157     if(setRecvInfo(env,info,callback_cont->rinfo) == 0)
158     {
159       #ifdef TEST_STAGE
160         printf(":!c: setRecvInfo() failed! \n");
161       #endif
162       break;
163     }
164     ////////////////////////////////////////////////////
165     // control print - only in TEST_STAGE
166     #ifdef TEST_STAGE
167       printf(":c: rinfo created :] \n");
168       printf(":c:----- ORTERecvInfo members  ------ \n");
169       printf(":c:    recvStatus: %d \n", info->status);
170       printf(":c:    senderGuid: hid = %d, aid = %d, oid = %d \n",
171              info->senderGUID.hid,info->senderGUID.aid,info->senderGUID.oid);
172       printf(":c:         topic: %s \n",info->topic);
173       printf(":c:          type: %s \n",info->type);
174       printf(":c: localTimeRecv: sec = %d, fract = %d \n",
175              info->localTimeReceived.seconds,info->localTimeReceived.fraction);
176       printf(":c: remoteTimePub: sec = %d, fract = %d \n",
177              info->remoteTimePublished.seconds,info->remoteTimePublished.fraction);
178       printf(":c:         seqNr: high = %d, low = %d \n",info->sn.high,info->sn.low);
179       printf(":c:---------------------------------- \n");
180     #endif
181     ////////////////////////////////////////////////////
182     // update MessageData instance
183     // get cls
184     cls_msg = (*env)->GetObjectClass(env, obj_msg);
185     //cls_tmp = (*env)->FindClass(env, "org/ocera/orte/types/MessageData");
186     if(cls_msg == 0)
187     {
188       #ifdef TEST_STAGE
189          printf(":!c: cls_msg = NULL \n");
190       #endif
191       break;
192     }
193     //
194     if (obj_bb == 0)
195     {
196       // get buff's fieldID
197       fid = (*env)->GetFieldID(env,
198                                cls_msg,
199                                "buffer",
200                                "Ljava/nio/ByteBuffer;");
201       if (fid == NULL)
202       {
203         #ifdef TEST_STAGE
204            printf(":!c: fid = NULL \n");
205         #endif
206         break;
207       }
208       // get buff's object
209       obj_bb = (*env)->GetObjectField(env, obj_msg, fid);
210       if(obj_bb == NULL)
211       {
212         #ifdef TEST_STAGE
213            printf(":!c: obj_bb = NULL \n");
214         #endif
215         break;
216       }
217       // create global reference
218       callback_cont->bbuff = (*env)->NewGlobalRef(env, obj_bb);
219       if (callback_cont->bbuff == 0)
220       {
221         #ifdef TEST_STAGE
222            printf(":!c: callback_cont->bbuff = NULL \n");
223         #endif
224         break;
225       }
226       #ifdef TEST_STAGE
227          printf(":c: global reference created.. \n");
228       #endif
229     }
230     // get class ByteBuffer
231     cls_bb = (*env)->GetObjectClass(env, obj_bb);
232     if(cls_bb == 0)
233     {
234       #ifdef TEST_STAGE
235          printf(":!c: cls_bb = NULL \n");
236       #endif
237       break;
238     }
239     // get buff's length
240     mid = (*env)->GetMethodID(env,
241                               cls_msg,
242                               "getMaxDataLength",
243                               "()I");
244     if(mid == 0)
245     {
246       #ifdef TEST_STAGE
247          printf(":!c: mid = NULL \n");
248       #endif
249       break;
250     }
251     buff_length = (*env)->CallIntMethod(env,
252                                         obj_msg,
253                                         mid);
254     // needs rewind buffer before working with it!!
255     // (needs cls Buffer not ByteBuffer!)
256     // get class Buffer
257     cls_tmp = (*env)->FindClass(env, "java/nio/Buffer");
258     if(cls_tmp == 0)
259     {
260       #ifdef TEST_STAGE
261          printf(":!c: cls_tmp = NULL \n");
262       #endif
263       break;
264     }
265     // methodID - rewind()
266     mid = (*env)->GetMethodID(env,
267                             cls_tmp,
268                             "rewind",
269                             "()Ljava/nio/Buffer;");
270     if(mid == 0)
271     {
272       #ifdef TEST_STAGE
273          printf(":!c: mid = NULL \n");
274       #endif
275       break;
276     }
277     // call method
278     (*env)->CallObjectMethod(env,
279                              obj_bb,
280                              mid);
281     #ifdef TEST_STAGE
282        printf(":c: buffer successfully rewind..\n");
283     #endif
284     // methodID - put()
285     mid = (*env)->GetMethodID(env,
286                               cls_bb,
287                               "put",
288                               "(B)Ljava/nio/ByteBuffer;");
289     if(mid == 0)
290     {
291       #ifdef TEST_STAGE
292          printf(":!c: mid = NULL \n");
293       #endif
294       break;
295     }
296     // copy the bytes from C to JAVA buffer
297     /////////////////////////////////////////////////////
298     buffer = (char *) vinstance;
299     //
300     for(i = 0; i < buff_length; i++)
301     {
302       #ifdef TEST_STAGE
303         printf(":c: i = %d kopirovany znak = %c [%d] \n",
304                i,*buffer,*buffer);
305       #endif
306       // call method
307       obj_bb = (*env)->CallObjectMethod(env,
308                                         obj_bb,
309                                         mid,
310                                         *buffer);
311       // next char
312       buffer++;
313     }
314     /////////////////////////////////////////////////////
315     // methodID - read()
316     mid = (*env)->GetMethodID(env,
317                               cls_msg,
318                               "read",
319                               "()V");
320     if(mid == 0)
321     {
322       #ifdef TEST_STAGE
323          printf(":!c: mid = NULL \n");
324       #endif
325       break;
326     }
327     // call method
328     (*env)->CallVoidMethod(env,
329                            obj_msg,
330                            mid);
331
332    /* *************************** *
333     *  call JAVA CallBack method  *
334     * *************************** */
335       #ifdef TEST_STAGE
336         printf(":c: call JAVA CallBack method \n");
337       #endif
338
339
340         // get class
341     cls = (*env)->GetObjectClass(env,callback_cont->obj);
342     if(cls == 0)
343     {
344       #ifdef TEST_STAGE
345         printf(":!c: cls = NULL \n");
346       #endif
347       break;
348     }
349     // get method ID
350     mid = (*env)->GetMethodID(env,
351                               cls,
352                               "callback",
353                               "(Lorg/ocera/orte/types/RecvInfo;Lorg/ocera/orte/types/MessageData;)V");
354     if(mid == 0)
355     {
356       #ifdef TEST_STAGE
357         printf(":!c: cls = NULL \n");
358       #endif
359       break;
360     }
361     mid_callback = mid;
362     //
363     #ifdef TEST_STAGE
364       printf(":c: volam callback metodu.. halo jsi tam?? \n");
365     #endif
366     // call object's method
367     (*env)->CallVoidMethod(env,
368                            callback_cont->obj, /*obj*/
369                            mid_callback,
370                            callback_cont->rinfo,
371                            NULL);//obj_msg);
372     // set flag
373     flag_ok = 1;
374   } while(0);
375
376   // detach current thread
377   if((*jvm)->DetachCurrentThread(jvm) != 0)
378      printf(":c!: DetachCurrentThread failed! \n");
379   //
380   #ifdef TEST_STAGE
381      printf(":c: ------------ thats all from recvCallBack ------------ \n\n");
382   #endif
383
384 }
385
386 /* ****************************************************************** *
387  *                            native method                           *
388  * ****************************************************************** */
389 JNIEXPORT jint JNICALL
390 Java_org_ocera_orte_Subscription_jORTESubscriptionCreate
391 (JNIEnv   *env,
392  jobject   obj,
393  jint      dhandle,   // appDomain handle
394  jint      jsmode,    // subs mode
395  jint      jstype,    // subs type
396  jstring   jtopic,    // subs topic
397  jstring   jtname,    // subs typeName
398  jint      jbufflen,  // length of buffer
399  jobject   obj_msg,   // messageData instance
400  jobject   jdeadline,
401  jobject   jminSeparation,
402  jobject   obj_callback,
403  jlong     j_multicastIP)
404 {
405   // jni variables
406   JavaVM                 *jvm;
407   jfieldID                fid;
408   jclass                  cls;
409   // orte variables
410   ORTESubscription       *s = 0;
411   ORTEDomain             *d;
412   SubscriptionMode        smode;
413   SubscriptionType        stype;
414   NtpTime                 deadline;
415   NtpTime                 minSeparation;
416   // jorte varialbe
417   JORTECallbackContext_t *callback_cont;
418   // standart variables
419   const char             *topic = 0;
420   const char             *typename = 0;
421   char                   *buffer;
422   int                     flag_ok = 0;
423   // memory alocation
424   // don't forget use free() funct.!!
425   callback_cont = (JORTECallbackContext_t*)malloc(sizeof(JORTECallbackContext_t));
426
427   do
428   {
429     // create buffer
430     buffer = (char*) malloc((int32_t) jbufflen);
431     // check obj_callback
432     if (obj_callback == 0)
433     {
434       #ifdef TEST_STAGE
435         printf(":!c: obj_callback = NULL \n");
436       #endif
437       break;
438     }
439     // get jvm
440     jint b = (*env)->GetJavaVM(env,&jvm);
441     if (b <  0)
442     {
443       #ifdef TEST_STAGE
444         printf(":!c: getJavaVM() failed! \n");
445       #endif
446       break;
447     }
448     if (b == 0)
449     {
450       #ifdef TEST_STAGE
451         printf(":c: getJavaVM succesfull.. \n");
452       #endif
453     }
454     callback_cont->jvm = jvm;
455     // create global references
456     callback_cont->obj = (*env)->NewGlobalRef(env, obj_callback);
457     //
458     if (callback_cont->obj == 0)
459     {
460       #ifdef TEST_STAGE
461         printf(":c: global reference not created! \n");
462       #endif
463       break;
464     }
465     // create global references
466     callback_cont->msg = (*env)->NewGlobalRef(env, obj_msg);
467     //
468     if (callback_cont->msg == 0)
469     {
470       #ifdef TEST_STAGE
471         printf(":c: global reference not created! \n");
472       #endif
473       break;
474     }
475     // init RecvInfo pointer
476     callback_cont->rinfo = 0;
477     callback_cont->bbuff = 0;
478     //
479     cls = (*env)->GetObjectClass(env, obj);
480     if(cls == 0)
481     {
482       #ifdef TEST_STAGE
483         printf(":!c: cls = NULL \n");
484       #endif
485       break;
486     }
487     // fieldID - callbackContextHandle
488     fid = (*env)->GetFieldID(env,
489                              cls,
490                              "callbackContextHandle",
491                              "I");
492     if(fid == 0)
493     {
494       #ifdef TEST_STAGE
495         printf(":!c: fid = NULL \n");
496       #endif
497       break;
498     }
499     (*env)->SetIntField(env,
500                         obj,
501                         fid,
502                         (int) callback_cont);
503     #ifdef TEST_STAGE
504        printf(":c: ORTESubscriptionCreate() calling..\n");
505     #endif
506     //
507     d = (ORTEDomain *) dhandle;
508     if (d == 0)
509     {
510       #ifdef TEST_STAGE
511         printf(":!c: d = NULL [bad domain handle] \n");
512       #endif
513       break;
514     }
515     //
516     smode = (SubscriptionMode) jsmode;
517     stype = (SubscriptionType) jstype;
518     topic = (*env)->GetStringUTFChars(env, jtopic, 0);
519     typename = (*env)->GetStringUTFChars(env, jtname, 0);
520     deadline = getNtpTime(env, jdeadline);//
521     minSeparation = getNtpTime(env, jminSeparation);//
522     // call ORTE function
523     s = ORTESubscriptionCreate(d,
524                                smode,
525                                stype,
526                                topic,
527                                typename,
528                                (void *) buffer,
529                                &deadline,
530                                &minSeparation,
531                                recvCallBack,
532                                (void*)callback_cont,
533                                (uint32_t) j_multicastIP);
534     if (s == 0)
535     {
536       #ifdef TEST_STAGE
537         printf(":!c: s = NULL [subscription not created] \n");
538       #endif
539       break;
540     }
541
542     // set flag
543     flag_ok = 1;
544   } while(0);
545
546   // free memory
547   (*env)->ReleaseStringUTFChars(env, jtopic, topic);
548   (*env)->ReleaseStringUTFChars(env, jtname, typename);
549   // returns handle of new created Subscription
550   if(flag_ok == 0) return 0;
551   return ((jint) s);
552
553 }