source: trunk/zoo-kernel/service_internal_js.c @ 263

Last change on this file since 263 was 42, checked in by djay, 14 years ago

Enhance the JavaScript? support by automatically load the ZOO-api.js and ZOO-proj4js.js file before loading the JavaScript? service. This way no more need to integrate the whole ZOO-api.js and proj4js.js files into the JavaScript? service provider code.

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