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

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

Fix bug #62. Use the same data structure in JS as in Python. Fix again bug #42.

File size: 14.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)+15];
106  sprintf(api0,"%s/%sZOO-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/%sZOO-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)+2];
129  sprintf(filename,"%s/%s%s",ntmp,tmpm1->value,tmpm2->value);
130  filename[strlen(tmpm1->value)+strlen(tmpm2->value)+strlen(ntmp)+1]=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#ifdef JS_DEBUG
332  fprintf(stderr,"Is finally an array ?\n");
333  if(JS_IsArrayObject(cx,tt)){
334    fprintf(stderr,"Is finally an array !\n");
335  }
336  else
337    fprintf(stderr,"Is not an array !\n");
338#endif
339  jsint len;
340  JSBool hasLen=JS_GetArrayLength(cx, tt, &len);
341  if(hasLen==JS_FALSE){
342#ifdef JS_DEBUG
343    fprintf(stderr,"outputs array is empty\n");
344#endif
345  }
346#ifdef JS_DEBUG
347  fprintf(stderr,"outputs array length : %d\n",len);
348#endif
349  for(oi=0;oi < len;oi++){
350#ifdef JS_DEBUG
351    fprintf(stderr,"outputs array length : %d step %d \n",len,oi);
352#endif
353    jsval tmp1;
354    JSBool hasElement=JS_GetElement(cx,tt,oi,&tmp1);
355    JSObject *otmp1=JSVAL_TO_OBJECT(tmp1);
356    JSIdArray *idp=JS_Enumerate(cx,otmp1);
357    if(idp!=NULL) {
358      int index;
359      jsdouble argNum;
360#ifdef JS_DEBUG
361      fprintf(stderr,"Properties length :  %d \n",idp->length);
362#endif
363      tres=(maps*)malloc(MAPS_SIZE);
364      tres->name=NULL;
365      tres->content=NULL;
366      tres->next=NULL;
367
368      for (index=0,argNum=idp->length;index<argNum;index++) { 
369        jsval id = idp->vector[index];
370        jsval vp;
371        JSString* str; 
372        JS_IdToValue(cx,id,&vp);
373        char *c, *tmp;
374        JSString *jsmsg;
375        size_t len1;
376        jsmsg = JS_ValueToString(cx,vp);
377        len1 = JS_GetStringLength(jsmsg);
378#ifdef JS_DEBUG
379        fprintf(stderr,"Enumerate id : %d => %s\n",oi,JS_EncodeString(cx,jsmsg));
380#endif
381        jsval nvp=JSVAL_NULL;
382        if((JS_GetProperty(cx, JSVAL_TO_OBJECT(tmp1), JS_EncodeString(cx,jsmsg), &nvp)==JS_FALSE)){
383#ifdef JS_DEBUG
384          fprintf(stderr,"Enumerate id : %d => %s => No more value\n",oi,JS_EncodeString(cx,jsmsg));
385#endif
386        }
387       
388        if(JSVAL_IS_OBJECT(nvp)){
389#ifdef JS_DEBUG
390          fprintf(stderr,"JSVAL NVP IS OBJECT\n");
391#endif
392        }
393
394        JSObject *nvp1=JSVAL_NULL;
395        JS_ValueToObject(cx,nvp,&nvp1);
396        jsval nvp1j=OBJECT_TO_JSVAL(nvp1);
397        if(JSVAL_IS_OBJECT(nvp1j)){
398          JSString *jsmsg1;
399          JSObject *nvp2=JSVAL_NULL;
400          jsmsg1 = JS_ValueToString(cx,nvp1j);
401          len1 = JS_GetStringLength(jsmsg1);
402#ifdef JS_DEBUG
403          fprintf(stderr,"JSVAL NVP1J IS OBJECT %s = %s\n",JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
404#endif
405          if(strcasecmp(JS_EncodeString(cx,jsmsg1),"[object Object]")==0){
406            tres->name=strdup(JS_EncodeString(cx,jsmsg));
407            tres->content=mapFromJSObject(cx,nvp1j);
408          }
409          else
410            if(strcasecmp(JS_EncodeString(cx,jsmsg),"name")==0){
411              tres->name=strdup(JS_EncodeString(cx,jsmsg1));
412            }
413            else{
414              if(tres->content==NULL)
415                tres->content=createMap(JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
416              else
417                addToMap(tres->content,JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
418            }
419        }
420#ifdef JS_DEBUG
421        else
422          fprintf(stderr,"JSVAL NVP1J IS NOT OBJECT !!\n");
423#endif
424
425      }
426#ifdef JS_DEBUG
427      dumpMaps(tres);
428#endif
429      if(res==NULL)
430        res=dupMaps(&tres);
431      else
432        addMapsToMaps(&res,tres);
433      freeMaps(&tres);
434      free(tres);
435      tres=NULL;
436
437    }
438  }
439#ifdef JS_DEBUG
440  dumpMaps(res);
441#endif
442  return res;
443}
444
445map* mapFromJSObject(JSContext *cx,jsval t){
446  map *res=NULL;
447  JSIdArray *idp=JS_Enumerate(cx,JSVAL_TO_OBJECT(t));
448#ifdef JS_DEBUG
449  fprintf(stderr,"Properties %p\n",(void*)t);
450#endif
451  if(idp!=NULL) {
452    int index;
453    jsdouble argNum;
454#ifdef JS_DEBUG
455    fprintf(stderr,"Properties length :  %d \n",idp->length);
456#endif
457    for (index=0,argNum=idp->length;index<argNum;index++) { 
458      jsval id = idp->vector[index];
459      jsval vp;
460      JSString* str; 
461      JS_IdToValue(cx,id,&vp);
462      char *c, *tmp;
463      JSString *jsmsg,*jsmsg1;
464      size_t len,len1;
465      jsmsg = JS_ValueToString(cx,vp);
466      len = JS_GetStringLength(jsmsg);
467      jsval nvp;
468      JS_GetProperty(cx, JSVAL_TO_OBJECT(t), JS_EncodeString(cx,jsmsg), &nvp);
469      jsmsg1 = JS_ValueToString(cx,nvp);
470      len1 = JS_GetStringLength(jsmsg1);
471#ifdef JS_DEBUG
472      fprintf(stderr,"Enumerate id : %d [ %s => %s ]\n",index,JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
473#endif
474      if(res!=NULL){
475#ifdef JS_DEBUG
476        fprintf(stderr,"%s - %s\n",JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
477#endif
478        addToMap(res,JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
479      }
480      else{
481        res=createMap(JS_EncodeString(cx,jsmsg),JS_EncodeString(cx,jsmsg1));
482        res->next=NULL;
483      }
484#ifdef JS_DEBUG
485      dumpMap(res);
486#endif
487    }
488  }
489#ifdef JS_DEBUG
490  dumpMap(res);
491#endif
492  return res;
493}
494
495/* The error reporter callback. */
496void reportError(JSContext *cx, const char *message, JSErrorReport *report)
497{
498  sprintf(dbg,"%s:%u:%s\n",
499          report->filename ? report->filename : "<no filename>",
500          (unsigned int) report->lineno,
501          message);
502#ifdef JS_DEBUG
503  fprintf(stderr,"%s",dbg);
504#endif
505  fflush(stderr);
506}
507
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