source: branches/prototype-v0/zoo-project/zoo-kernel/service_internal_mono.c @ 933

Last change on this file since 933 was 933, checked in by knut, 5 years ago

Resolve certain string-related type conflicts, e.g., char* vs. const char* or char[N], that may cause errors in some build environments. Resolve a problem with the include order of fcgi_stdio.h (note: should verify that this harmonizes with resolution of same problem in trunk).

  • Property svn:keywords set to Id
File size: 16.9 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * ref. http://www.mono-project.com/docs/advanced/embedding/
5 *      http://www.mono-project.com/docs/advanced/pinvoke/
6 *      http://www.giorgosdimtsas.net/embedding-mono-in-your-c-application/
7 *
8 * Copyright (c) 2009-2013 GeoLabs SARL
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 */
28
29#include "service_internal_mono.h"
30#include "response_print.h"
31
32MonoClass *iclasses[4];
33MonoMethod *imethods[10];
34
35/**
36 * Load a Mono dll then run the static public method corresponding to the
37 * service by passing the conf, inputs and outputs parameters.
38 *
39 * @param main_conf the conf maps containing the main.cfg settings
40 * @param request the map containing the HTTP request
41 * @param s the service structure
42 * @param real_inputs the maps containing the inputs
43 * @param real_outputs the maps containing the outputs
44 */
45int zoo_mono_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
46  maps* m=*main_conf;
47  maps* inputs=*real_inputs;
48  maps* outputs=*real_outputs;
49  char *ntmp=NULL;
50  map* tmp=getMap(request,"metapath");
51  char *classpath;
52  char *oclasspath;
53  int res=SERVICE_FAILED;
54  MonoAssembly* assembly;
55  MonoImage* monoImage;
56
57  static char LIB[] = "/usr/lib";
58  static char ETC[] = "/etc";
59 
60  char* libPath = LIB;
61  char* etcPath = ETC;
62  map* libPathMap=getMapFromMaps(*main_conf,"mono","lib");
63  map* etcPathMap=getMapFromMaps(*main_conf,"mono","etc");
64  if(libPathMap!=NULL)
65    libPath=libPathMap->value;
66  if(etcPathMap!=NULL)
67    etcPath=etcPathMap->value;
68 
69  mono_set_dirs(libPath,etcPath);
70
71  map* configMap=getMapFromMaps(*main_conf,"mono","config");
72  if(configMap!=NULL)
73    mono_config_parse(configMap->value);
74  else
75    mono_config_parse(NULL);
76
77  MonoDomain* monoDomain;
78  map* mono;
79  if (hasvalue(*main_conf, "mono", "version", &mono)) {   
80          monoDomain = mono_jit_init_version("ZOO_Embedded_Domain", mono->value);
81  }
82  else {         
83          monoDomain = mono_jit_init("ZOO_Embedded_Domain"); // use default framework version
84  }
85
86  //MonoDomain* monoDomain = mono_jit_init_version("ZOO_Embedded_Domain", "v4.0.30319");
87  //MonoDomain* monoDomain = mono_jit_init("ZOO_Embedded_Domain"); 
88
89  const char* ZMapsLib = "ZMaps.dll";
90  char *zooAssembly = NULL;
91 
92  map* config = NULL, *basedir = NULL;
93  if (hasvalue(*main_conf, "mono", "configdir", &basedir) && // knut: rename to e.g. "base_dir"?
94          hasvalue(*main_conf, "mono", "configfile", &config)) {         
95          mono_domain_set_config(monoDomain, basedir->value, config->value); 
96          zooAssembly = file_exists(basedir->value, ZMapsLib);
97  }
98  else {         
99          mono_domain_set_config(monoDomain, "./", "");
100  }   
101
102  map* cwdMap;
103  if (! hasvalue(*main_conf, "main", "servicePath", &cwdMap) &&
104          ! hasvalue(*main_conf, "main", "libPath", &cwdMap) ) {
105          cwdMap = getMapFromMaps(*main_conf, "lenv", "cwd");
106  } 
107
108  if (zooAssembly != NULL || (zooAssembly = file_exists(cwdMap->value, ZMapsLib)) != NULL) {
109          assembly = mono_domain_assembly_open(monoDomain, zooAssembly);
110  }
111  else { 
112          // try to load from default locations (GAC?)
113          assembly = mono_domain_assembly_open(monoDomain, ZMapsLib);
114  } 
115  free(zooAssembly);
116
117  if (assembly == NULL) {
118          setMapInMaps(*main_conf, "lenv", "message", _("The ZMaps.dll assembly cannot be found!"));
119          return 4;
120  }
121
122  mono_add_internal_call ("ZOO_API::Translate", MonoTranslate);   
123  mono_add_internal_call("ZOO_API::UpdateStatus", MonoUpdateStatus);
124 
125  monoImage = mono_assembly_get_image(assembly);
126  MonoClass *KeysList = mono_class_from_name(monoImage, "ZooGenerics", "KeysList");
127  MonoClass *ZMapsClass = mono_class_from_name(monoImage, "ZooGenerics", "ZMaps");
128  MonoMethod *ZMapsAdd = mono_class_get_method_from_name(ZMapsClass, "addToMaps", 2); 
129  MonoMethod *ZMapsGetMaps = mono_class_get_method_from_name(ZMapsClass, "getMaps", 1);
130  MonoClass *_ZMapsClass = mono_class_from_name(monoImage, "ZooGenerics", "_ZMaps");
131  MonoMethod *_ZMapsSetContent = mono_class_get_method_from_name(_ZMapsClass, "setContent", 1);
132  MonoMethod *_ZMapsSetChild = mono_class_get_method_from_name(_ZMapsClass, "setChild", 1);
133  MonoMethod *_ZMapsGetContent = mono_class_get_method_from_name(_ZMapsClass, "getContent", 0);
134  MonoMethod *_ZMapsGetChild = mono_class_get_method_from_name(_ZMapsClass, "getChild", 0);
135  MonoClass *ZMapClass = mono_class_from_name(monoImage, "ZooGenerics", "ZMap");
136  MonoMethod *ZMapGetMap = mono_class_get_method_from_name(ZMapClass, "getMap", 1);
137  MonoMethod *ZMapAdd = mono_class_get_method_from_name(ZMapClass, "addToMap", 2);
138  MonoMethod *ZMapDisplay = mono_class_get_method_from_name(ZMapClass, "display", 1);
139  MonoObject *exc=NULL;
140
141  MonoClass *classes[3]={_ZMapsClass,ZMapsClass,ZMapClass};
142  MonoMethod *methods[5]={ZMapsAdd,_ZMapsSetContent,_ZMapsSetChild,ZMapAdd,ZMapDisplay};
143 
144  MonoMethod *ZMapsGetKeys = mono_class_get_method_from_name(ZMapsClass, "getKeys", 0);
145 
146  MonoMethod *ZMapsGetKeysCount = mono_class_get_method_from_name(ZMapsClass, "getKeysCount", 0);
147  MonoMethod *ZMapsGetKey = mono_class_get_method_from_name(ZMapsClass, "getKey", 1);
148  MonoMethod *ZMapGetKeys = mono_class_get_method_from_name(ZMapClass, "getKeys", 0);
149  MonoClassField *ZMapKeys = mono_class_get_field_from_name(ZMapClass, "Keys");
150  MonoMethod *ZMapGetKeysCount = mono_class_get_method_from_name(ZMapClass, "getKeysCount", 0);
151  MonoMethod *ZMapGetKey = mono_class_get_method_from_name(ZMapClass, "getKey", 1);
152  MonoMethod *ZMapGetSize = mono_class_get_method_from_name(ZMapClass, "getSize", 0);
153  MonoMethod *ZMapGetMapAsBytes = mono_class_get_method_from_name(ZMapClass, "getMapAsBytes", 0);
154  MonoClass *oclasses[4]={_ZMapsClass,ZMapsClass,ZMapClass,KeysList};
155  MonoMethod *omethods[10]={ZMapsGetMaps,ZMapsGetKeysCount,ZMapsGetKey,ZMapGetMap,ZMapGetKeysCount,ZMapGetKey,_ZMapsGetContent,_ZMapsGetChild,ZMapGetSize,ZMapGetMapAsBytes};
156 
157  for(int i=0;i<4;i++){
158    iclasses[i]=oclasses[i];
159    imethods[i]=omethods[i];
160  }
161  for(int i=4;i<10;i++)
162    imethods[i]=omethods[i];
163
164  void *args[3];
165
166  MonoObject * main=ZMapsFromMaps(monoDomain,classes,methods,&exc,m);
167
168  MonoObject * in=ZMapsFromMaps(monoDomain,classes,methods,&exc,inputs);
169
170  MonoObject * out=ZMapsFromMaps(monoDomain,classes,methods,&exc,outputs);
171 
172  args [0] = main;
173  args [1] = in;
174  args [2] = out;
175
176  char* sName = NULL;
177  MonoAssembly* serviceAssembly = NULL;
178 
179  tmp = getMap(s->content, "serviceProvider"); 
180  char* test = file_exists(NULL, "log.txt");
181  if ( (sName = file_exists(cwdMap->value, tmp->value)) != NULL ||
182           (sName = file_exists(".", tmp->value)) != NULL ||  // in case servicePath is defined but serviceProvider is in working directory
183           (basedir != NULL && (sName = file_exists(basedir->value, tmp->value)) != NULL) ) {
184
185           serviceAssembly = mono_domain_assembly_open(monoDomain, sName);
186  }
187  else {
188          // try to open from default locations   
189          serviceAssembly = mono_domain_assembly_open(monoDomain, tmp->value);
190  }
191  free(sName);
192
193  //char *sName=(char*)malloc((strlen(tmp->value)+strlen(cwdMap->value)+2)*sizeof(char));
194  //sprintf(sName,"%s/%s",cwdMap->value,tmp->value);
195  //MonoAssembly* serviceAssembly = mono_domain_assembly_open(monoDomain,sName);
196 
197  if(serviceAssembly==NULL){
198    char *msg=(char*)malloc((strlen(_("Your service assembly: %s cannot be found!"))+strlen(tmp->value)+1)*sizeof(char));
199    sprintf(msg,_("Your service assembly %s cannot be found!"),tmp->value);
200    setMapInMaps(*main_conf,"lenv","message",msg);
201    free(msg);
202    return 4;
203  }
204 
205  MonoImage* serviceImage = mono_assembly_get_image(serviceAssembly);
206
207  map* tmp1=getMap(s->content,"serviceNameSpace");
208 
209  tmp=getMap(s->content,"serviceClass");
210  MonoClass *serviceClass = mono_class_from_name(serviceImage, tmp1->value, tmp->value);
211  if(serviceClass==NULL){
212    char *msg=(char*)malloc((strlen(_("Your service class method %s::%s cannot be found!"))+strlen(tmp1->value)+strlen(tmp->value)+1)*sizeof(char));
213    sprintf(msg,_("Your service class method %s::%s cannot be found!"),tmp1->value,tmp->value);
214    setMapInMaps(*main_conf,"lenv","message",msg);
215    free(msg);
216    return 4;
217  }
218 
219  MonoMethod *serviceFunction = mono_class_get_method_from_name(serviceClass, s->name, 3);
220  if(serviceFunction==NULL){
221    char *msg=(char*)malloc((strlen(_("Your service static method %s cannot be found!"))+strlen(s->name)+1)*sizeof(char));
222    sprintf(msg,_("Your service static method %s cannot be found!"),s->name);
223    setMapInMaps(*main_conf,"lenv","message",msg);
224    free(msg);
225    return 4;
226  }
227 
228  MonoObject *exception=NULL;
229  MonoObject *result = mono_runtime_invoke(serviceFunction,NULL,args,&exception);
230 
231  if (exception != NULL) { // knut: add exception handling
232          MonoString* pMsg = mono_object_to_string(exception, NULL);     
233          setErrorMessage(*main_conf, s->name, NoApplicableCode, mono_string_to_utf8(pMsg));
234          return 4;
235  }
236
237  res=*(int*)mono_object_unbox (result);
238 
239  if(res==3){
240    freeMaps(&outputs);
241    free(outputs);
242    outputs=mapsFromZMaps(monoDomain,oclasses,omethods,(MonoObject*)args[2]);
243    *real_outputs=outputs;
244  }
245 
246  freeMaps(&m);
247  free(m);
248  m=mapsFromZMaps(monoDomain,oclasses,omethods,(MonoObject*)args[0]);
249  *main_conf=m;
250  mono_jit_cleanup (monoDomain); 
251  return res;
252}
253
254/**
255 * Create ZMaps from maps
256 * @param domain the Mono Domain
257 * @param classes the Mono classes required to create (_ZMaps,ZMaps and ZMap)
258 * @param methods the Mono methods required (ZMapsAdd, _ZMapsSetContent, _ZMapsSetChild, ZMapAdd and ZMapDisplay)
259 * @param m the maps to use as source to create the corresponding ZMaps
260 * @return MonoObject* to a new ZMap
261 */
262MonoObject* ZMapsFromMaps(MonoDomain* domain,MonoClass **classes,MonoMethod **methods,MonoObject **exc,maps* m){
263  MonoObject *res=mono_object_new(domain,classes[1]);
264  MonoMethod* constructorMethod = mono_class_get_method_from_name(classes[1],
265                                                                  ".ctor",
266                                                                  0);
267  mono_runtime_invoke(constructorMethod, res, NULL, exc);
268  MonoMethod* constructorMethod1 = mono_class_get_method_from_name(classes[0],
269                                                                   ".ctor",
270                                                                   0);
271 
272  while(m!=NULL){
273    MonoObject *tmpRes=mono_object_new(domain,classes[0]);
274    mono_runtime_invoke(constructorMethod1, tmpRes, NULL, exc);
275    void *values0 [1];
276    MonoObject* content = ZMapFromMap (domain,classes[2],methods,exc,m->content);
277    values0 [0] = content;
278    MonoObject *exception=NULL;
279    mono_runtime_invoke(methods[1],tmpRes,values0,&exception);
280    if(exception!=NULL)
281      {
282        fprintf(stderr,"ERROR : %s\n", mono_string_to_utf8(mono_object_to_string(exception, NULL)));
283        fflush(stderr);
284        return res;
285      }
286    if(m->child!=NULL){
287      void *values [1];
288      values [0] = ZMapsFromMaps (domain,classes,methods,exc,m->child);
289      mono_runtime_invoke(methods[2],tmpRes,values,exc);
290    }
291    void *values [2];
292    values [0] = mono_string_new (domain, m->name);
293    values [1] = tmpRes;
294    mono_runtime_invoke(methods[0],res,values,exc);
295    m=m->next;
296  }
297  return res;
298}
299
300/**
301 * Create ZMap from map
302 * @param domain the Mono Domain
303 * @param classes the Mono classes required to create (_ZMaps,ZMaps and ZMap)
304 * @param methods the Mono methods required (ZMapsAdd, _ZMapsSetContent, _ZMapsSetChild, ZMapAdd and ZMapDisplay)
305 * @param exc the Mono exception object
306 * @param m the map to use as source to create a new ZMap
307 * @return MonoObject* to a new ZMap
308 */
309MonoObject* ZMapFromMap(MonoDomain* domain,MonoClass *ZMapClass,MonoMethod **methods,MonoObject **exc,map* m){
310  MonoObject *res=mono_object_new(domain,ZMapClass);
311  MonoMethod* constructorMethod = mono_class_get_method_from_name(ZMapClass,
312                                                                  ".ctor",
313                                                                  0);
314  mono_runtime_invoke(constructorMethod, res, NULL, exc);
315  map* sizeMap=getMap(m,"size");
316  while(m!=NULL){
317    void *values [2];
318    MonoString* name = mono_string_new(domain, m->name);
319    MonoString* value;
320    if(sizeMap!=NULL && strcasecmp(m->name,"value")==0)
321      value = mono_string_new_len(domain, m->value,atoi(sizeMap->value));
322    else
323      value = mono_string_new(domain, m->value);
324    values [0] = name;
325    values [1] = value;
326    mono_runtime_invoke(methods[3],res,values,exc);
327    m=m->next;
328  }
329  return res;
330}
331
332/**
333 * Create maps from ZMaps
334 * @param domain the Mono Domain
335 * @param classes the Mono classes required to create (_ZMapsClass,ZMapsClass,ZMapClass,KeysList)
336 * @param methods the Mono methods required (ZMapsGetMaps,ZMapsGetKeysCount,ZMapsGetKey,ZMapGetMap,ZMapGetKeysCount,ZMapGetKey,_ZMapsGetContent,_ZMapsGetChild)
337 * @param m the ZMaps to use as source to create a new maps
338 * @return MonoObject* to a new ZMaps
339 */
340maps* mapsFromZMaps(MonoDomain* domain,MonoClass **classes,MonoMethod **methods,MonoObject* m){
341  maps* res=NULL;
342  if(m!=NULL){
343    MonoObject *exc=NULL;
344    MonoObject *okeys = mono_runtime_invoke(methods[1],m,NULL,&exc);
345    if(exc!=NULL)
346      {
347        fprintf(stderr,"ERROR : %s\n", mono_string_to_utf8(mono_object_to_string(exc, NULL)));
348        fflush(stderr);
349        return res;
350      }
351
352    int keyCount=*(int*)mono_object_unbox (okeys);
353    for(int i=0;i<keyCount;i++){
354      void* values[1];
355      values[0]=&i;
356      exc=NULL;
357      MonoString *okey = (MonoString*) mono_runtime_invoke(methods[2],m,values,&exc);
358      char* key = mono_string_to_utf8(okey);
359      maps* tmp=createMaps(key);
360      values[0]=mono_string_new (domain, key);
361      MonoString *content_ZMaps = (MonoString*) mono_runtime_invoke(methods[0],m,values,&exc);
362      MonoObject *content = mono_runtime_invoke(methods[6],(MonoObject*)content_ZMaps,NULL,&exc);
363      tmp->content=mapFromZMap(domain,classes,methods,content);
364      MonoObject *childs = mono_runtime_invoke(methods[7],content_ZMaps,NULL,&exc);
365      tmp->child=mapsFromZMaps(domain,classes,methods,childs);
366      if(res==NULL){
367        res=dupMaps(&tmp);
368      }else
369        addMapsToMaps(&res,tmp);
370      freeMaps(&tmp);
371      free(tmp);
372      mono_free(key);
373    }
374  }
375  return res;
376}
377
378/**
379 * Create map from ZMap
380 * @param domain the Mono Domain
381 * @param classes the Mono classes required (_ZMapsClass,ZMapsClass,ZMapClass,KeysList)
382 * @param methods the Mono methods required (ZMapsGetMaps,ZMapsGetKeysCount,ZMapsGetKey,ZMapGetMap,ZMapGetKeysCount,ZMapGetKey,_ZMapsGetContent,_ZMapsGetChild,ZMapGetSize)
383 * @param m the ZMap to use as source to create a new map
384 * @return MonoObject* to a new ZMap
385 */
386map* mapFromZMap(MonoDomain* domain,MonoClass **classes,MonoMethod **methods,MonoObject* m){
387  map* res=NULL;
388  if(m!=NULL){
389    MonoObject *exc = NULL;
390    MonoObject *okeys = mono_runtime_invoke(methods[4],m,NULL,&exc);
391    int keyCount=*(int*)mono_object_unbox (okeys);
392    MonoObject *osize = mono_runtime_invoke(methods[8],m,NULL,&exc);
393    int size=*(int*)mono_object_unbox (osize);
394    for(int i=0;i<keyCount;i++){
395      void* values[1];
396      values[0]=&i;
397      exc=NULL;
398      MonoString *okey = (MonoString*) mono_runtime_invoke(methods[5],m,values,&exc);
399      char* key = mono_string_to_utf8(okey);
400      values[0]=mono_string_new (domain, key);
401      exc=NULL;
402      MonoString *ovalue = (MonoString*) mono_runtime_invoke(methods[3],m,values,&exc);
403      char* value = mono_string_to_utf8(ovalue);
404      if(res==NULL)
405        res=createMap(key,value);
406      else
407        addToMap(res,key,value);
408    }
409  }
410  return res;
411}
412
413/**
414 * The translate function to search in zoo-services gettext domain for translating a string.
415 * @param str the string to be translated
416 * @return the translated string
417 */
418static MonoString* MonoTranslate(MonoString *str){
419  return mono_string_new (mono_domain_get(), _(mono_string_to_utf8(str)));
420}
421
422/**
423 * The updateStatus function to update the ongoing status of a ZOO-Service.
424 * @param m the main.cfg map
425 * @param str the message for the current step
426 * @param p the percentage of the
427 * @return the translated string
428 */
429static void MonoUpdateStatus(MonoObject* obj, MonoString *str, int p) { 
430        MonoDomain* domain = mono_object_get_domain(obj);       
431        maps *confMaps = mapsFromZMaps(domain, iclasses, imethods, obj);       
432        setMapInMaps(confMaps, "lenv", "message", mono_string_to_utf8(str));   
433        int tmp = p > 100 || p < 0 ? -1 : p;   
434        char tmpStatus[5];
435        snprintf(tmpStatus, 4, "%d", tmp);     
436        setMapInMaps(confMaps, "lenv", "status", (char*)tmpStatus);     
437        _updateStatus(confMaps);       
438        freeMaps(&confMaps);   
439        free(confMaps);
440        return;
441}
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

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