source: trunk/zoo-project/zoo-kernel/service_internal_js.c @ 333

Last change on this file since 333 was 333, checked in by djay, 13 years ago

Small update to support similar outputs for JavaScript? services as Python ones. Still support old format.

File size: 15.0 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2010 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.h"
26
27static char dbg[1024];
28
29JSBool
30JSAlert(JSContext *cx, uintN argc, jsval *argv1)
31{
32  jsval *argv = JS_ARGV(cx,argv1);
33  int i=0;
34  JS_MaybeGC(cx);
35  for(i=0;i<argc;i++){
36    JSString* jsmsg = JS_ValueToString(cx,argv[i]);
37    fprintf(stderr,"[ZOO-API:JS] %s\n",JS_EncodeString(cx,jsmsg));
38  }
39  JS_MaybeGC(cx);
40 
41  return JS_TRUE;
42}
43
44int zoo_js_support(maps** main_conf,map* request,service* s,
45                   maps **inputs,maps **outputs)
46{
47  maps* main=*main_conf;
48  maps* _inputs=*inputs;
49  maps* _outputs=*outputs;
50
51  /* The class of the global object. */
52  JSClass global_class = {
53    "global", JSCLASS_GLOBAL_FLAGS,
54    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
55    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
56    JSCLASS_NO_OPTIONAL_MEMBERS
57  };
58
59  /* JS variables. */
60  JSRuntime *rt;
61  JSContext *cx;
62  JSObject  *global;
63
64  /* Create a JS runtime. */
65  rt = JS_NewRuntime(8L * 1024L * 1024L);
66  if (rt == NULL)
67    return 1;
68 
69  /* Create a context. */
70  cx = JS_NewContext(rt,8192);
71  if (cx == NULL){
72    return 1;
73  }
74  JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT );//| JSOPTION_METHODJIT);
75  JS_SetVersion(cx, JSVERSION_LATEST);
76  JS_SetErrorReporter(cx, reportError);
77
78  /* Create the global object. */
79  //#ifdef JS_NewCompartmentAndGlobalObject
80  global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
81  //#else
82  //global = JS_NewObject(cx, &global_class, NULL,NULL);
83  //#endif
84
85  /* Populate the global object with the standard globals,
86     like Object and Array. */
87  if (!JS_InitStandardClasses(cx, global)){
88    return 1;
89  }
90
91  if (!JS_DefineFunction(cx, global, "ZOORequest", JSRequest, 4, 0))
92    return 1;
93  if (!JS_DefineFunction(cx, global, "ZOOUpdateStatus", JSUpdateStatus, 2, 0))
94    return 1;
95  if (!JS_DefineFunction(cx, global, "alert", JSAlert, 2, 0))
96    return 1;
97
98  map* tmpm1=getMap(request,"metapath");
99  char ntmp[1024];
100  getcwd(ntmp,1024);
101
102  /**
103   * Load the first part of the ZOO-API
104   */
105  char api0[strlen(tmpm1->value)+strlen(ntmp)+16];
106  sprintf(api0,"%s/%s/ZOO-proj4js.js",ntmp,tmpm1->value);
107#ifdef JS_DEBUG
108  fprintf(stderr,"Trying to load %s\n",api0);
109#endif
110  JSObject *api_script1=loadZooApiFile(cx,global,api0);
111  fflush(stderr);
112
113  char api1[strlen(tmpm1->value)+strlen(ntmp)+11];
114  sprintf(api1,"%s/%s/ZOO-api.js",ntmp,tmpm1->value);
115#ifdef JS_DEBUG
116  fprintf(stderr,"Trying to load %s\n",api1);
117#endif
118  JSObject *api_script2=loadZooApiFile(cx,global,api1);
119  fflush(stderr);
120
121  /* Your application code here. This may include JSAPI calls
122     to create your own custom JS objects and run scripts. */
123  maps* out=*outputs;
124  int res=SERVICE_FAILED;
125  maps* mc=*main_conf;
126  map* tmpm2=getMap(s->content,"serviceProvider");
127
128  char filename[strlen(tmpm1->value)+strlen(tmpm2->value)+strlen(ntmp)+3];
129  sprintf(filename,"%s/%s/%s",ntmp,tmpm1->value,tmpm2->value);
130  filename[strlen(tmpm1->value)+strlen(tmpm2->value)+strlen(ntmp)+2]=0;
131#ifdef JS_DEBUG
132  fprintf(stderr,"FILENAME %s\n",filename);
133#endif
134  struct stat file_status;
135  stat(filename, &file_status);
136  char source[file_status.st_size];
137  uint16 lineno;
138  jsval rval;
139  JSBool ok ;
140  JSObject *script = JS_CompileFile(cx, global, filename);
141  if(script!=NULL){
142    (void)JS_ExecuteScript(cx, global, script, &rval);
143  }
144  else{
145    char tmp1[1024];
146    sprintf(tmp1,"Unable to load JavaScript file %s",filename);
147    map* err=createMap("text",tmp1);
148    addMapToMap(&err,createMap("code","NoApplicableCode"));
149    printExceptionReportResponse(mc,err);
150    JS_DestroyContext(cx);
151    JS_DestroyRuntime(rt);
152    JS_ShutDown();
153    exit(-1);
154  }
155  /* Call a function in obj's scope. */
156  jsval argv[3];
157  JSObject *jsargv1=JSObject_FromMaps(cx,*main_conf);
158  argv[0] = OBJECT_TO_JSVAL(jsargv1);
159  JSObject *jsargv2=JSObject_FromMaps(cx,*inputs);
160  argv[1] = OBJECT_TO_JSVAL(jsargv2);
161  JSObject *jsargv3=JSObject_FromMaps(cx,*outputs);
162  argv[2] = OBJECT_TO_JSVAL(jsargv3);
163  jsval rval1=JSVAL_NULL;
164#ifdef JS_DEBUG
165  fprintf(stderr, "object %p\n", (void *) argv[2]);
166#endif
167
168  ok = JS_CallFunctionName(cx, global, s->name, 3, argv, &rval1);
169
170#ifdef JS_DEBUG
171  fprintf(stderr, "object %p\n", (void *) argv[2]);
172#endif
173
174  JSObject *d;
175  if (ok==JS_TRUE && JSVAL_IS_OBJECT(rval1)==JS_TRUE) {
176#ifdef JS_DEBUG
177    fprintf(stderr,"Function run sucessfully !\n");
178#endif
179    /* Should get a number back from the service function call. */
180    ok = JS_ValueToObject(cx, rval1, &d);
181  }else{
182    /* Unable to run JS function */
183    char tmp1[1024];
184    if(strlen(dbg)==0)
185      sprintf(dbg,"No result was found after the function call");
186    sprintf(tmp1,"Unable to run %s from the JavaScript file %s : \n %s",s->name,filename,dbg);
187#ifdef JS_DEBUG
188    fprintf(stderr,"%s",tmp1);
189#endif
190    map* err=createMap("text",tmp1);
191    addToMap(err,"code","NoApplicableCode");
192    printExceptionReportResponse(*main_conf,err);
193    freeMap(&err);
194    free(err);
195    JS_DestroyContext(cx);
196    JS_DestroyRuntime(rt);
197    JS_ShutDown();
198    // Should return -1 here but the unallocation won't work from zoo_service_loader.c line 1847
199    exit(-1);
200  }
201
202  jsval t=OBJECT_TO_JSVAL(d);
203  if(JS_IsArrayObject(cx,d)){
204#ifdef JS_DEBUG
205    fprintf(stderr,"An array was returned !\n");
206#endif
207    jsint len;
208    if((JS_GetArrayLength(cx, d, &len)==JS_FALSE)){
209#ifdef JS_DEBUG
210      fprintf(stderr,"outputs array is empty\n");
211#endif
212    }
213    jsval tmp1;
214    JSBool hasResult=JS_GetElement(cx,d,0,&tmp1);
215    res=JSVAL_TO_INT(tmp1);
216#ifdef JS_DEBUG
217    fprintf(stderr," * %d * \n",res);
218#endif
219    jsval tmp2;
220    JSBool hasElement=JS_GetElement(cx,d,1,&tmp2);
221    if(hasElement==JS_TRUE){
222      *outputs=mapsFromJSObject(cx,tmp2);
223    }
224  }
225  else{
226#ifdef JS_DEBUG
227    fprintf(stderr,"The serice didn't return an array !\n");
228#endif
229    jsval tmp1;
230    JSBool hasResult=JS_GetProperty(cx,d,"result",&tmp1);
231    res=JSVAL_TO_INT(tmp1);
232
233#ifdef JS_DEBUG
234    fprintf(stderr," * %d * \n",res);
235#endif
236    jsval tmp2;
237    JSBool hasElement=JS_GetProperty(cx,d,"outputs",&tmp2);
238#ifdef JS_DEBUG
239    if(!hasElement)
240      fprintf(stderr,"No outputs property returned\n");
241    if(JS_IsArrayObject(cx,JSVAL_TO_OBJECT(tmp2)))
242      fprintf(stderr,"outputs is array an as expected\n");
243    else
244      fprintf(stderr,"outputs is not an array as expected\n");
245#endif
246    *outputs=mapsFromJSObject(cx,tmp2);
247#ifdef JS_DEBUG
248    dumpMaps(outputs);
249#endif
250  }
251
252  /* Cleanup. */
253  JS_DestroyContext(cx);
254  JS_DestroyRuntime(rt);
255  JS_ShutDown();
256#ifdef JS_DEBUG
257  fprintf(stderr,"Returned value %d\n",res);
258#endif
259  return res;
260}
261
262JSObject * loadZooApiFile(JSContext *cx,JSObject  *global, char* filename){
263  struct stat api_status;
264  int s=stat(filename, &api_status);
265  if(s==0){
266    jsval rval;
267    JSBool ok ;
268    JSObject *script = JS_CompileFile(cx, JS_GetGlobalObject(cx), filename);
269    if(script!=NULL){
270      (void)JS_ExecuteScript(cx, JS_GetGlobalObject(cx), script, &rval);
271#ifdef JS_DEBUG
272      fprintf(stderr,"**************\n%s correctly loaded\n**************\n",filename);
273#endif
274      return script;
275    }
276#ifdef JS_DEBUG
277    else
278      fprintf(stderr,"\n**************\nUnable to run %s\n**************\n",filename);
279#endif
280  }
281#ifdef JS_DEBUG
282  else
283    fprintf(stderr,"\n**************\nUnable to load %s\n**************\n",filename);
284#endif
285  return NULL;
286}
287
288JSObject* JSObject_FromMaps(JSContext *cx,maps* t){
289
290  JSObject* res=JS_NewObject(cx, NULL, NULL, NULL);
291  //JSObject *res = JS_NewArrayObject(cx, 0, NULL);
292  if(res==NULL)
293    fprintf(stderr,"Array Object is NULL!\n");
294  maps* tmp=t;
295
296  while(tmp!=NULL){
297    jsuint len;
298    JSObject* res1=JS_NewObject(cx, NULL, NULL, NULL);
299    JSObject *pval=JSObject_FromMap(cx,tmp->content);
300    jsval pvalj=OBJECT_TO_JSVAL(pval);
301    JS_SetProperty(cx, res, tmp->name, &pvalj);
302
303#ifdef JS_DEBUG
304    fprintf(stderr,"Length of the Array %d, element : %s added \n",len,tmp->name);
305#endif
306    tmp=tmp->next;
307  } 
308  return res;
309}
310
311JSObject* JSObject_FromMap(JSContext *cx,map* t){
312  JSObject* res=JS_NewObject(cx, NULL, NULL, NULL);
313  jsval resf =  OBJECT_TO_JSVAL(res);
314  map* tmpm=t;
315  while(tmpm!=NULL){
316    jsval jsstr = STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpm->value,strlen(tmpm->value)));
317    JS_SetProperty(cx, res, tmpm->name,&jsstr);
318#ifdef JS_DEBUG
319    fprintf(stderr,"%s => %s\n",tmpm->name,tmpm->value);
320#endif
321    tmpm=tmpm->next;
322  }
323  return res;
324}
325
326maps* mapsFromJSObject(JSContext *cx,jsval t){
327  maps *res=NULL;
328  maps *tres=NULL;
329  jsint oi=0;
330  JSObject* tt=JSVAL_TO_OBJECT(t);
331  if(JS_IsArrayObject(cx,tt)){
332#ifdef JS_DEBUG
333    fprintf(stderr,"Is finally an array !\n");
334#endif
335  }
336  else{
337#ifdef JS_DEBUG
338    fprintf(stderr,"Is not an array !\n");
339#endif
340    JSIdArray *idp=JS_Enumerate(cx,tt);
341    if(idp!=NULL) {
342      int index;
343      jsdouble argNum;
344#ifdef JS_DEBUG
345      fprintf(stderr,"Properties length :  %d \n",idp->length);
346#endif
347     
348      for (index=0,argNum=idp->length;index<argNum;index++) { 
349        jsval id = idp->vector[index];
350        jsval vp;
351        JSString* str; 
352        JS_IdToValue(cx,id,&vp);
353        char *c, *tmp;
354        JSString *jsmsg;
355        size_t len1;
356        jsmsg = JS_ValueToString(cx,vp);
357        len1 = JS_GetStringLength(jsmsg);
358
359        tres=(maps*)malloc(MAPS_SIZE);
360        tres->name=strdup(JS_EncodeString(cx,jsmsg));
361        tres->content=NULL;
362        tres->next=NULL;
363
364        jsval nvp=JSVAL_NULL;
365        if((JS_GetProperty(cx, JSVAL_TO_OBJECT(tt), JS_EncodeString(cx,jsmsg), &nvp)==JS_FALSE)){
366#ifdef JS_DEBUG
367          fprintf(stderr,"Enumerate id : %d => %s => No more value\n",oi,JS_EncodeString(cx,jsmsg));
368#endif
369        }
370       
371        JSObject *nvp1=JSVAL_NULL;
372        JS_ValueToObject(cx,nvp,&nvp1);
373        jsval nvp1j=OBJECT_TO_JSVAL(nvp1);
374        if(JSVAL_IS_OBJECT(nvp1j)){
375          tres->content=mapFromJSObject(cx,nvp1j);
376        }
377
378        if(res==NULL)
379          res=dupMaps(&tres);
380        else
381          addMapsToMaps(&res,tres);
382        freeMaps(&tres);
383        free(tres);
384        tres=NULL;
385       
386       
387      }
388    }
389  }
390
391  jsint len;
392  JSBool hasLen=JS_GetArrayLength(cx, tt, &len);
393  if(hasLen==JS_FALSE){
394#ifdef JS_DEBUG
395    fprintf(stderr,"outputs array is empty\n");
396#endif
397  }
398#ifdef JS_DEBUG
399  fprintf(stderr,"outputs array length : %d\n",len);
400#endif
401  for(oi=0;oi < len;oi++){
402#ifdef JS_DEBUG
403    fprintf(stderr,"outputs array length : %d step %d \n",len,oi);
404#endif
405    jsval tmp1;
406    JSBool hasElement=JS_GetElement(cx,tt,oi,&tmp1);
407    JSObject *otmp1=JSVAL_TO_OBJECT(tmp1);
408    JSIdArray *idp=JS_Enumerate(cx,otmp1);
409    if(idp!=NULL) {
410      int index;
411      jsdouble argNum;
412#ifdef JS_DEBUG
413      fprintf(stderr,"Properties length :  %d \n",idp->length);
414#endif
415      tres=(maps*)malloc(MAPS_SIZE);
416      tres->name=NULL;
417      tres->content=NULL;
418      tres->next=NULL;
419
420      for (index=0,argNum=idp->length;index<argNum;index++) { 
421        jsval id = idp->vector[index];
422        jsval vp;
423        JSString* str; 
424        JS_IdToValue(cx,id,&vp);
425        char *c, *tmp;
426        JSString *jsmsg;
427        size_t len1;
428        jsmsg = JS_ValueToString(cx,vp);
429        len1 = JS_GetStringLength(jsmsg);
430#ifdef JS_DEBUG
431        fprintf(stderr,"Enumerate id : %d => %s\n",oi,JS_EncodeString(cx,jsmsg));
432#endif
433        jsval nvp=JSVAL_NULL;
434        if((JS_GetProperty(cx, JSVAL_TO_OBJECT(tmp1), JS_EncodeString(cx,jsmsg), &nvp)==JS_FALSE)){
435#ifdef JS_DEBUG
436          fprintf(stderr,"Enumerate id : %d => %s => No more value\n",oi,JS_EncodeString(cx,jsmsg));
437#endif
438        }
439       
440        if(JSVAL_IS_OBJECT(nvp)){
441#ifdef JS_DEBUG
442          fprintf(stderr,"JSVAL NVP IS OBJECT\n");
443#endif
444        }
445
446        JSObject *nvp1=JSVAL_NULL;
447        JS_ValueToObject(cx,nvp,&nvp1);
448        jsval nvp1j=OBJECT_TO_JSVAL(nvp1);
449        if(JSVAL_IS_OBJECT(nvp1j)){
450          JSString *jsmsg1;
451          JSObject *nvp2=JSVAL_NULL;
452          jsmsg1 = JS_ValueToString(cx,nvp1j);
453          len1 = JS_GetStringLength(jsmsg1);
454#ifdef JS_DEBUG
455          fprintf(stderr,"JSVAL NVP1J IS OBJECT %s = %s\n",JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
456#endif
457          if(strcasecmp(JS_EncodeString(cx,jsmsg1),"[object Object]")==0){
458            tres->name=strdup(JS_EncodeString(cx,jsmsg));
459            tres->content=mapFromJSObject(cx,nvp1j);
460          }
461          else
462            if(strcasecmp(JS_EncodeString(cx,jsmsg),"name")==0){
463              tres->name=strdup(JS_EncodeString(cx,jsmsg1));
464            }
465            else{
466              if(tres->content==NULL)
467                tres->content=createMap(JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
468              else
469                addToMap(tres->content,JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
470            }
471        }
472#ifdef JS_DEBUG
473        else
474          fprintf(stderr,"JSVAL NVP1J IS NOT OBJECT !!\n");
475#endif
476
477      }
478#ifdef JS_DEBUG
479      dumpMaps(tres);
480#endif
481      if(res==NULL)
482        res=dupMaps(&tres);
483      else
484        addMapsToMaps(&res,tres);
485      freeMaps(&tres);
486      free(tres);
487      tres=NULL;
488
489    }
490  }
491#ifdef JS_DEBUG
492  dumpMaps(res);
493#endif
494  return res;
495}
496
497map* mapFromJSObject(JSContext *cx,jsval t){
498  map *res=NULL;
499  JSIdArray *idp=JS_Enumerate(cx,JSVAL_TO_OBJECT(t));
500#ifdef JS_DEBUG
501  fprintf(stderr,"Properties %p\n",(void*)t);
502#endif
503  if(idp!=NULL) {
504    int index;
505    jsdouble argNum;
506#ifdef JS_DEBUG
507    fprintf(stderr,"Properties length :  %d \n",idp->length);
508#endif
509    for (index=0,argNum=idp->length;index<argNum;index++) { 
510      jsval id = idp->vector[index];
511      jsval vp;
512      JSString* str; 
513      JS_IdToValue(cx,id,&vp);
514      char *c, *tmp;
515      JSString *jsmsg,*jsmsg1;
516      size_t len,len1;
517      jsmsg = JS_ValueToString(cx,vp);
518      len = JS_GetStringLength(jsmsg);
519      jsval nvp;
520      JS_GetProperty(cx, JSVAL_TO_OBJECT(t), JS_EncodeString(cx,jsmsg), &nvp);
521      jsmsg1 = JS_ValueToString(cx,nvp);
522      len1 = JS_GetStringLength(jsmsg1);
523#ifdef JS_DEBUG
524      fprintf(stderr,"Enumerate id : %d [ %s => %s ]\n",index,JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
525#endif
526      if(res!=NULL){
527#ifdef JS_DEBUG
528        fprintf(stderr,"%s - %s\n",JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
529#endif
530        addToMap(res,JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
531      }
532      else{
533        res=createMap(JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
534        res->next=NULL;
535      }
536#ifdef JS_DEBUG
537      dumpMap(res);
538#endif
539    }
540  }
541#ifdef JS_DEBUG
542  dumpMap(res);
543#endif
544  return res;
545}
546
547/* The error reporter callback. */
548void reportError(JSContext *cx, const char *message, JSErrorReport *report)
549{
550  sprintf(dbg,"%s:%u:%s\n",
551          report->filename ? report->filename : "<no filename>",
552          (unsigned int) report->lineno,
553          message);
554#ifdef JS_DEBUG
555  fprintf(stderr,"%s",dbg);
556#endif
557  fflush(stderr);
558}
559
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