source: trunk/zoo-project/zoo-kernel/service_internal_ruby.c @ 546

Last change on this file since 546 was 459, checked in by djay, 11 years ago

Initial introduction of Value and Range in AllowedValues?, update zcfg documentation. Return valid Status code when returning ExceptionRepport?.

File size: 11.0 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2014 GeoLabs SARL
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "service_internal_ruby.h"
26
27#if RUBY_API_VERSION_MAJOR >= 2 || RUBY_API_VERSION_MINOR == 9
28int argc=0;
29char **argv=NULL;
30#endif
31
32int zoo_ruby_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
33#if RUBY_API_VERSION_MAJOR >= 2 || RUBY_API_VERSION_MINOR == 9
34  ruby_sysinit(&argc,&argv);
35  RUBY_INIT_STACK;
36#endif
37  ruby_init();
38  maps* m=*main_conf;
39  maps* inputs=*real_inputs;
40  maps* outputs=*real_outputs;
41  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
42  char *ntmp=tmp0->value;
43  map* tmp=NULL;
44  ruby_init_loadpath();
45  ruby_script("ZOO_EMBEDDED_ENV");
46 
47  VALUE klass=rb_define_module("Zoo");
48  rb_define_const(klass,"SERVICE_SUCCEEDED",INT2FIX(3));
49  rb_define_const(klass,"SERVICE_FAILED",INT2FIX(4));
50  typedef VALUE (*HOOK)(...);
51  rb_define_module_function(klass,"Translate",reinterpret_cast<HOOK>(RubyTranslate),-1);
52  rb_define_module_function(klass,"UpdateStatus",reinterpret_cast<HOOK>(RubyUpdateStatus),-1);
53
54  int error = 0;
55               
56  ID rFunc=Qnil;
57  tmp=getMap(s->content,"serviceProvider");
58  if(tmp!=NULL){
59#if RUBY_VERSION_MINOR == 8
60    const char* script = ruby_sourcefile = rb_source_filename(tmp->value);
61    rb_protect(LoadWrap, reinterpret_cast<VALUE>(script), &error);
62#else
63    rb_load_protect(rb_str_new2(tmp->value), 0, &error);
64#endif
65    if(error) {
66      ruby_trace_error(m);
67      return -1;
68    }
69#if RUBY_VERSION_MINOR == 8
70    ruby_exec();
71#else
72    ruby_exec_node(NULL);
73#endif
74  }
75  else{
76    map* err=createMap("text","Unable to parse serviceProvider please check your zcfg file.");
77    addToMap(err,"code","NoApplicableCode");
78    printExceptionReportResponse(m,err);
79    return -1;
80  }
81  int res=SERVICE_FAILED;
82  rFunc=rb_intern(s->name);
83  if(rFunc!=Qnil){
84    VALUE arg1=RubyHash_FromMaps(m);
85    VALUE arg2=RubyHash_FromMaps(inputs);
86    VALUE arg3=RubyHash_FromMaps(outputs);
87    VALUE rArgs[3]={arg1,arg2,arg3};
88    if (!rArgs)
89      return -1;
90    struct my_callback data;
91    data.obj=Qnil;
92    data.method_id=rFunc;
93    data.nargs=3;
94    data.args[0]=rArgs[0];
95    data.args[1]=rArgs[1];
96    data.args[2]=rArgs[2];
97    typedef VALUE (*HOOK)(VALUE);
98    VALUE tres=rb_protect(reinterpret_cast<HOOK>(FunCallWrap),(VALUE)(&data),&error);
99    if (TYPE(tres) == T_FIXNUM) {
100      res=FIX2INT(tres);
101      freeMaps(real_outputs);
102      free(*real_outputs);
103      freeMaps(main_conf);
104      free(*main_conf);
105      *main_conf=mapsFromRubyHash(arg1);
106      *real_outputs=mapsFromRubyHash(arg3);
107#ifdef DEBUG
108      dumpMaps(*main_conf);
109      dumpMaps(*real_outputs);
110#endif
111    }else{
112      ruby_trace_error(m);
113      res=-1;
114    }
115  }
116  else{
117    char tmpS[1024];
118    sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
119    map* tmps=createMap("text",tmpS);
120    printExceptionReportResponse(m,tmps);
121    res=-1;
122  }
123  ruby_finalize();
124  return res;
125}
126
127VALUE LoadWrap(VALUE arg) {
128  const char *filename = reinterpret_cast<const char*>(arg);
129  rb_load_file(filename);
130  return Qnil;
131}
132
133VALUE FunCallWrap(VALUE rdata) {
134  struct my_callback* data = (struct my_callback*) rdata;
135  return rb_funcall2(data->obj,data->method_id,data->nargs,data->args);
136}
137
138void ruby_trace_error(maps* m){
139#if RUBY_VERSION_MINOR == 8
140  VALUE lasterr = rb_gv_get("$!");
141#else
142  VALUE lasterr = rb_errinfo();
143  VALUE ruby_errinfo = lasterr;
144#endif
145  VALUE message = rb_obj_as_string(lasterr);
146  VALUE lklass = rb_class_path(CLASS_OF(lasterr));
147#if RUBY_VERSION_MINOR == 8
148  char *trace=(char*)malloc((strlen(RSTRING(lklass)->ptr)+strlen(RSTRING(message)->ptr)+3)*sizeof(char));
149  sprintf(trace,"%s: %s",RSTRING_PTR(lklass),RSTRING_PTR(message));
150#else
151  char *trace=(char*)malloc((strlen(RSTRING_PTR(lklass))+strlen(RSTRING_PTR(message))+3)*sizeof(char));
152  sprintf(trace,"%s: %s",RSTRING_PTR(lklass),RSTRING_PTR(message));
153#endif
154  if(!NIL_P(ruby_errinfo))
155    {
156      VALUE ary = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
157      int c;
158      for (c=0; c<RARRAY_LEN(ary); c++) {
159        int len=strlen(trace);
160        char *tmp0=zStrdup(trace);
161#if RUBY_VERSION_MINOR == 8
162        trace=(char *) realloc(trace,(len+strlen(RSTRING(RARRAY(ary)->ptr[c])->ptr)+2)*sizeof(char));
163        sprintf(trace,"%s\n%s",tmp0,RSTRING(RARRAY(ary)->ptr[c])->ptr);
164#else
165        trace=(char *) realloc(trace,(len+strlen(RSTRING_PTR(RARRAY_PTR(ary)[c]))+2)*sizeof(char));
166        sprintf(trace,"%s\n%s",tmp0,RSTRING_PTR(RARRAY_PTR(ary)[c]));
167#endif
168        free(tmp0);
169      }
170    }
171  map* err=createMap("text",trace);
172  addToMap(err,"code","NoApplicableCode");
173  printExceptionReportResponse(m,err);
174}
175
176VALUE RubyHash_FromMaps(maps* t){
177  VALUE res=rb_hash_new();
178  maps* tmp=t;
179  while(tmp!=NULL){
180    VALUE value=RubyHash_FromMap(tmp->content);
181    VALUE name=rb_str_new2(tmp->name);
182    rb_hash_aset(res,name,value);
183    tmp=tmp->next;
184  } 
185  return res;
186}
187
188int
189keys_i(VALUE key,VALUE value,VALUE ary)
190{
191  if (key == Qundef) return ST_CONTINUE;
192  rb_ary_push(ary, key);
193  return ST_CONTINUE;
194}
195
196VALUE
197rb_hash_size(VALUE hash)
198{
199    return INT2FIX(RHASH_TBL(hash)->num_entries);
200}
201
202VALUE RubyHash_FromMap(map* t){
203  VALUE res=rb_hash_new( );
204  map* tmp=t;
205  int hasSize=0;
206  map* isArray=getMap(tmp,"isArray");
207  map* size=getMap(tmp,"size");
208  map* tmap=getMapType(tmp);
209  while(tmp!=NULL){
210    VALUE name= rb_str_new2(tmp->name);
211    if(strcasecmp(tmp->name,"value")==0) {
212      if(isArray!=NULL){
213        map* len=getMap(tmp,"length");
214        int cnt=atoi(len->value);
215        VALUE value=rb_ary_new2(cnt);
216        VALUE mvalue=rb_ary_new2(cnt);
217        VALUE svalue=rb_ary_new2(cnt);
218
219        for(int i=0;i<cnt;i++){
220         
221          map* vMap=getMapArray(tmp,"value",i);     
222          map* sMap=getMapArray(tmp,"size",i);
223
224          if(vMap!=NULL){
225           
226            VALUE lvalue;
227            VALUE lsvalue;
228            if(sMap==NULL){
229              lvalue=rb_str_new2(vMap->value);
230              lsvalue=Qnil;
231            }
232            else{
233              lvalue=rb_str_new(vMap->value,atoi(sMap->value));
234              lsvalue=rb_str_new2(sMap->value);
235              hasSize=1;
236            }
237
238            rb_ary_push(value,lvalue);
239            rb_ary_push(svalue,lsvalue);
240          }
241         
242          map* mMap=getMapArray(tmp,tmap->name,i);
243
244          VALUE lmvalue;
245          if(mMap!=NULL){
246            lmvalue=rb_str_new2(mMap->value);
247          }else
248            lmvalue=Qnil;
249          rb_ary_push(mvalue,lmvalue);
250         
251        }
252
253        rb_hash_aset(res, name, mvalue);
254        rb_hash_aset(res, rb_str_new2(tmap->name), mvalue);
255     
256        if(hasSize>0){
257          VALUE lname=rb_str_new2("size");
258          rb_hash_aset(res, lname, value);
259        }
260      }
261      else if(size!=NULL){
262        VALUE value=rb_str_new(tmp->value,atoi(size->value));
263        rb_hash_aset(res, name, value);
264      }
265      else{
266        VALUE value=rb_str_new2(tmp->value);
267        rb_hash_aset(res, name, value);
268      }
269    }
270    else{
271      VALUE value=rb_str_new2(tmp->value);
272      rb_hash_aset(res, name, value);
273    }
274    tmp=tmp->next;
275  }
276  return res;
277}
278
279
280maps* mapsFromRubyHash(VALUE t){
281  maps* res=NULL;
282  maps* cursor=res;
283  VALUE list;
284  list = rb_ary_new();
285  typedef int (*HOOK)(...);
286  rb_hash_foreach(t, reinterpret_cast<HOOK>(keys_i), list);
287  int nb=rb_hash_size(t);
288  int i;
289  for(i=0;i<FIX2INT(nb);i++){
290    VALUE key=rb_ary_pop(list);
291    VALUE value=rb_hash_aref(t,key);
292#ifdef DEBUG
293    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
294            StringValueCStr(key),StringValueCStr(value));
295#endif
296    cursor=(maps*)malloc(MAPS_SIZE);
297    cursor->name=StringValueCStr(key);
298    cursor->content=mapFromRubyHash(value);
299    cursor->next=NULL;
300    if(res==NULL)
301      res=dupMaps(&cursor);
302    else
303      addMapsToMaps(&res,cursor);
304    freeMap(&cursor->content);
305    free(cursor->content);
306    free(cursor);
307  }
308  return res;
309}
310
311map* mapFromRubyHash(VALUE t){
312  map* res=NULL;
313  VALUE list;
314  list = rb_ary_new();
315  typedef int (*HOOK)(...);
316  rb_hash_foreach(t,reinterpret_cast<HOOK>(keys_i), list);
317  int nb=RHASH_TBL(t)->num_entries;
318  int i;
319  for(i=0;i<nb;i++){
320    VALUE key=rb_ary_pop(list);
321    VALUE value=rb_hash_aref(t,key);
322#ifdef DEBUG
323    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
324            StringValueCStr(key),StringValueCStr(value));
325#endif
326    if(strcmp(StringValueCStr(key),"value")==0){
327      char *buffer=NULL;
328      int size=RSTRING_LEN(value);
329      buffer=StringValueCStr(value);
330      if(res!=NULL){
331        addToMap(res,StringValueCStr(key),"");
332      }else{
333        res=createMap(StringValueCStr(key),"");
334      }
335      map* tmpR=getMap(res,"value");
336      free(tmpR->value);
337      tmpR->value=(char*)malloc((size+1)*sizeof(char));
338      memmove(tmpR->value,buffer,size*sizeof(char));
339      tmpR->value[size]=0;
340      char sin[1024];
341      sprintf(sin,"%d",size);
342      addToMap(res,"size",sin);
343    }else{
344      if(res!=NULL){
345        addToMap(res,StringValueCStr(key),StringValueCStr(value));
346      }
347      else{
348        res=
349          createMap(StringValueCStr(key),StringValueCStr(value));
350      }
351    }
352  }
353  return res;
354}
355
356VALUE
357RubyTranslate(int argc, VALUE *argv, VALUE obj)
358{
359  return rb_str_new2(_ss(StringValueCStr(argv[0])));
360}
361
362VALUE
363RubyUpdateStatus(int argc, VALUE *argv, VALUE obj)
364{
365  maps* conf;
366  VALUE confdict=argv[0];
367  int istatus=argv[1];
368  char* status;
369  if (istatus < 0 || istatus > 100){
370    fprintf(stderr,"Status must be a percentage.");
371    return Qnil;
372  }else{
373     char tmpStatus[4];
374     snprintf(tmpStatus, 4, "%i", istatus);
375     status = zStrdup(tmpStatus);
376  }
377  /* now update the map */
378  {
379    VALUE lenv = rb_hash_aref(confdict,rb_str_new2("lenv"));
380    if(TYPE(lenv)!=T_NIL){
381      VALUE valobj=rb_str_new2(status);
382      rb_hash_aset(lenv,rb_str_new2("status"),valobj);
383    }
384  }
385  conf = mapsFromRubyHash(confdict);
386  if (getMapFromMaps(conf,"lenv","status") != NULL){
387    fprintf(stderr,"STATUS RETURNED : %s\n",status);
388    if(status!=NULL){
389      setMapInMaps(conf,"lenv","status",status);
390      free(status);
391    }
392    else
393      setMapInMaps(conf,"lenv","status","15");
394    updateStatus(conf);
395  }
396  freeMaps(&conf);
397  free(conf);
398  return Qnil;
399}
400
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png