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

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

Added some recent changes from trunk (r889), including some new utility functions and exception handling and new (conditional) definition of type bool. Added some new logic concerning Python and Mono environment and search paths. Fixed problem with Mono updateStatus function. Changed response_print.h to #include locale.h unconditionally and xlocale.h conditionally; xlocale.h is non-standard and can probably be dropped.

  • Property svn:keywords set to Id
File size: 16.8 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  char* libPath="/usr/lib";
58  char* etcPath="/etc";
59  map* libPathMap=getMapFromMaps(*main_conf,"mono","lib");
60  map* etcPathMap=getMapFromMaps(*main_conf,"mono","etc");
61  if(libPathMap!=NULL)
62    libPath=libPathMap->value;
63  if(etcPathMap!=NULL)
64    etcPath=etcPathMap->value;
65 
66  mono_set_dirs(libPath,etcPath);
67
68  map* configMap=getMapFromMaps(*main_conf,"mono","config");
69  if(configMap!=NULL)
70    mono_config_parse(configMap->value);
71  else
72    mono_config_parse(NULL);
73
74  MonoDomain* monoDomain;
75  map* mono;
76  if (hasvalue(*main_conf, "mono", "version", &mono)) {   
77          monoDomain = mono_jit_init_version("ZOO_Embedded_Domain", mono->value);
78  }
79  else {         
80          monoDomain = mono_jit_init("ZOO_Embedded_Domain"); // use default framework version
81  }
82
83  //MonoDomain* monoDomain = mono_jit_init_version("ZOO_Embedded_Domain", "v4.0.30319");
84  //MonoDomain* monoDomain = mono_jit_init("ZOO_Embedded_Domain"); 
85
86  char* ZMapsLib = "ZMaps.dll";
87  char *zooAssembly = NULL;
88 
89  map* config = NULL, *basedir = NULL;
90  if (hasvalue(*main_conf, "mono", "configdir", &basedir) && // knut: rename to e.g. "base_dir"?
91          hasvalue(*main_conf, "mono", "configfile", &config)) {         
92          mono_domain_set_config(monoDomain, basedir->value, config->value); 
93          zooAssembly = file_exists(basedir->value, ZMapsLib);
94  }
95  else {         
96          mono_domain_set_config(monoDomain, "./", "");
97  }   
98
99  map* cwdMap;
100  if (! hasvalue(*main_conf, "main", "servicePath", &cwdMap) &&
101          ! hasvalue(*main_conf, "main", "libPath", &cwdMap) ) {
102          cwdMap = getMapFromMaps(*main_conf, "lenv", "cwd");
103  } 
104
105  if (zooAssembly != NULL || (zooAssembly = file_exists(cwdMap->value, ZMapsLib)) != NULL) {
106          assembly = mono_domain_assembly_open(monoDomain, zooAssembly);
107  }
108  else { 
109          // try to load from default locations (GAC?)
110          assembly = mono_domain_assembly_open(monoDomain, ZMapsLib);
111  } 
112  free(zooAssembly);
113
114  if (assembly == NULL) {
115          setMapInMaps(*main_conf, "lenv", "message", _("The ZMaps.dll assembly cannot be found!"));
116          return 4;
117  }
118
119  mono_add_internal_call ("ZOO_API::Translate", MonoTranslate);   
120  mono_add_internal_call("ZOO_API::UpdateStatus", MonoUpdateStatus);
121 
122  monoImage = mono_assembly_get_image(assembly);
123  MonoClass *KeysList = mono_class_from_name(monoImage, "ZooGenerics", "KeysList");
124  MonoClass *ZMapsClass = mono_class_from_name(monoImage, "ZooGenerics", "ZMaps");
125  MonoMethod *ZMapsAdd = mono_class_get_method_from_name(ZMapsClass, "addToMaps", 2); 
126  MonoMethod *ZMapsGetMaps = mono_class_get_method_from_name(ZMapsClass, "getMaps", 1);
127  MonoClass *_ZMapsClass = mono_class_from_name(monoImage, "ZooGenerics", "_ZMaps");
128  MonoMethod *_ZMapsSetContent = mono_class_get_method_from_name(_ZMapsClass, "setContent", 1);
129  MonoMethod *_ZMapsSetChild = mono_class_get_method_from_name(_ZMapsClass, "setChild", 1);
130  MonoMethod *_ZMapsGetContent = mono_class_get_method_from_name(_ZMapsClass, "getContent", 0);
131  MonoMethod *_ZMapsGetChild = mono_class_get_method_from_name(_ZMapsClass, "getChild", 0);
132  MonoClass *ZMapClass = mono_class_from_name(monoImage, "ZooGenerics", "ZMap");
133  MonoMethod *ZMapGetMap = mono_class_get_method_from_name(ZMapClass, "getMap", 1);
134  MonoMethod *ZMapAdd = mono_class_get_method_from_name(ZMapClass, "addToMap", 2);
135  MonoMethod *ZMapDisplay = mono_class_get_method_from_name(ZMapClass, "display", 1);
136  MonoObject *exc=NULL;
137
138  MonoClass *classes[3]={_ZMapsClass,ZMapsClass,ZMapClass};
139  MonoMethod *methods[5]={ZMapsAdd,_ZMapsSetContent,_ZMapsSetChild,ZMapAdd,ZMapDisplay};
140 
141  MonoMethod *ZMapsGetKeys = mono_class_get_method_from_name(ZMapsClass, "getKeys", 0);
142 
143  MonoMethod *ZMapsGetKeysCount = mono_class_get_method_from_name(ZMapsClass, "getKeysCount", 0);
144  MonoMethod *ZMapsGetKey = mono_class_get_method_from_name(ZMapsClass, "getKey", 1);
145  MonoMethod *ZMapGetKeys = mono_class_get_method_from_name(ZMapClass, "getKeys", 0);
146  MonoClassField *ZMapKeys = mono_class_get_field_from_name(ZMapClass, "Keys");
147  MonoMethod *ZMapGetKeysCount = mono_class_get_method_from_name(ZMapClass, "getKeysCount", 0);
148  MonoMethod *ZMapGetKey = mono_class_get_method_from_name(ZMapClass, "getKey", 1);
149  MonoMethod *ZMapGetSize = mono_class_get_method_from_name(ZMapClass, "getSize", 0);
150  MonoMethod *ZMapGetMapAsBytes = mono_class_get_method_from_name(ZMapClass, "getMapAsBytes", 0);
151  MonoClass *oclasses[4]={_ZMapsClass,ZMapsClass,ZMapClass,KeysList};
152  MonoMethod *omethods[10]={ZMapsGetMaps,ZMapsGetKeysCount,ZMapsGetKey,ZMapGetMap,ZMapGetKeysCount,ZMapGetKey,_ZMapsGetContent,_ZMapsGetChild,ZMapGetSize,ZMapGetMapAsBytes};
153 
154  for(int i=0;i<4;i++){
155    iclasses[i]=oclasses[i];
156    imethods[i]=omethods[i];
157  }
158  for(int i=4;i<10;i++)
159    imethods[i]=omethods[i];
160
161  void *args[3];
162
163  MonoObject * main=ZMapsFromMaps(monoDomain,classes,methods,&exc,m);
164
165  MonoObject * in=ZMapsFromMaps(monoDomain,classes,methods,&exc,inputs);
166
167  MonoObject * out=ZMapsFromMaps(monoDomain,classes,methods,&exc,outputs);
168 
169  args [0] = main;
170  args [1] = in;
171  args [2] = out;
172
173  char* sName = NULL;
174  MonoAssembly* serviceAssembly = NULL;
175 
176  tmp = getMap(s->content, "serviceProvider"); 
177  char* test = file_exists(NULL, "log.txt");
178  if ( (sName = file_exists(cwdMap->value, tmp->value)) != NULL ||
179           (sName = file_exists(".", tmp->value)) != NULL ||  // in case servicePath is defined but serviceProvider is in working directory
180           (basedir != NULL && (sName = file_exists(basedir->value, tmp->value)) != NULL) ) {
181
182           serviceAssembly = mono_domain_assembly_open(monoDomain, sName);
183  }
184  else {
185          // try to open from default locations   
186          serviceAssembly = mono_domain_assembly_open(monoDomain, tmp->value);
187  }
188  free(sName);
189
190  //char *sName=(char*)malloc((strlen(tmp->value)+strlen(cwdMap->value)+2)*sizeof(char));
191  //sprintf(sName,"%s/%s",cwdMap->value,tmp->value);
192  //MonoAssembly* serviceAssembly = mono_domain_assembly_open(monoDomain,sName);
193 
194  if(serviceAssembly==NULL){
195    char *msg=(char*)malloc((strlen(_("Your service assembly: %s cannot be found!"))+strlen(tmp->value)+1)*sizeof(char));
196    sprintf(msg,_("Your service assembly %s cannot be found!"),tmp->value);
197    setMapInMaps(*main_conf,"lenv","message",msg);
198    free(msg);
199    return 4;
200  }
201 
202  MonoImage* serviceImage = mono_assembly_get_image(serviceAssembly);
203
204  map* tmp1=getMap(s->content,"serviceNameSpace");
205 
206  tmp=getMap(s->content,"serviceClass");
207  MonoClass *serviceClass = mono_class_from_name(serviceImage, tmp1->value, tmp->value);
208  if(serviceClass==NULL){
209    char *msg=(char*)malloc((strlen(_("Your service class method %s::%s cannot be found!"))+strlen(tmp1->value)+strlen(tmp->value)+1)*sizeof(char));
210    sprintf(msg,_("Your service class method %s::%s cannot be found!"),tmp1->value,tmp->value);
211    setMapInMaps(*main_conf,"lenv","message",msg);
212    free(msg);
213    return 4;
214  }
215 
216  MonoMethod *serviceFunction = mono_class_get_method_from_name(serviceClass, s->name, 3);
217  if(serviceFunction==NULL){
218    char *msg=(char*)malloc((strlen(_("Your service static method %s cannot be found!"))+strlen(s->name)+1)*sizeof(char));
219    sprintf(msg,_("Your service static method %s cannot be found!"),s->name);
220    setMapInMaps(*main_conf,"lenv","message",msg);
221    free(msg);
222    return 4;
223  }
224 
225  MonoObject *exception=NULL;
226  MonoObject *result = mono_runtime_invoke(serviceFunction,NULL,args,&exception);
227 
228  if (exception != NULL) { // knut: add exception handling
229          MonoString* pMsg = mono_object_to_string(exception, NULL);     
230          setErrorMessage(*main_conf, s->name, NoApplicableCode, mono_string_to_utf8(pMsg));
231          return 4;
232  }
233
234  res=*(int*)mono_object_unbox (result);
235 
236  if(res==3){
237    freeMaps(&outputs);
238    free(outputs);
239    outputs=mapsFromZMaps(monoDomain,oclasses,omethods,(MonoObject*)args[2]);
240    *real_outputs=outputs;
241  }
242 
243  freeMaps(&m);
244  free(m);
245  m=mapsFromZMaps(monoDomain,oclasses,omethods,(MonoObject*)args[0]);
246  *main_conf=m;
247  mono_jit_cleanup (monoDomain); 
248  return res;
249}
250
251/**
252 * Create ZMaps from maps
253 * @param domain the Mono Domain
254 * @param classes the Mono classes required to create (_ZMaps,ZMaps and ZMap)
255 * @param methods the Mono methods required (ZMapsAdd, _ZMapsSetContent, _ZMapsSetChild, ZMapAdd and ZMapDisplay)
256 * @param m the maps to use as source to create the corresponding ZMaps
257 * @return MonoObject* to a new ZMap
258 */
259MonoObject* ZMapsFromMaps(MonoDomain* domain,MonoClass **classes,MonoMethod **methods,MonoObject **exc,maps* m){
260  MonoObject *res=mono_object_new(domain,classes[1]);
261  MonoMethod* constructorMethod = mono_class_get_method_from_name(classes[1],
262                                                                  ".ctor",
263                                                                  0);
264  mono_runtime_invoke(constructorMethod, res, NULL, exc);
265  MonoMethod* constructorMethod1 = mono_class_get_method_from_name(classes[0],
266                                                                   ".ctor",
267                                                                   0);
268 
269  while(m!=NULL){
270    MonoObject *tmpRes=mono_object_new(domain,classes[0]);
271    mono_runtime_invoke(constructorMethod1, tmpRes, NULL, exc);
272    void *values0 [1];
273    MonoObject* content = ZMapFromMap (domain,classes[2],methods,exc,m->content);
274    values0 [0] = content;
275    MonoObject *exception=NULL;
276    mono_runtime_invoke(methods[1],tmpRes,values0,&exception);
277    if(exception!=NULL)
278      {
279        fprintf(stderr,"ERROR : %s\n", mono_string_to_utf8(mono_object_to_string(exception, NULL)));
280        fflush(stderr);
281        return res;
282      }
283    if(m->child!=NULL){
284      void *values [1];
285      values [0] = ZMapsFromMaps (domain,classes,methods,exc,m->child);
286      mono_runtime_invoke(methods[2],tmpRes,values,exc);
287    }
288    void *values [2];
289    values [0] = mono_string_new (domain, m->name);
290    values [1] = tmpRes;
291    mono_runtime_invoke(methods[0],res,values,exc);
292    m=m->next;
293  }
294  return res;
295}
296
297/**
298 * Create ZMap from map
299 * @param domain the Mono Domain
300 * @param classes the Mono classes required to create (_ZMaps,ZMaps and ZMap)
301 * @param methods the Mono methods required (ZMapsAdd, _ZMapsSetContent, _ZMapsSetChild, ZMapAdd and ZMapDisplay)
302 * @param exc the Mono exception object
303 * @param m the map to use as source to create a new ZMap
304 * @return MonoObject* to a new ZMap
305 */
306MonoObject* ZMapFromMap(MonoDomain* domain,MonoClass *ZMapClass,MonoMethod **methods,MonoObject **exc,map* m){
307  MonoObject *res=mono_object_new(domain,ZMapClass);
308  MonoMethod* constructorMethod = mono_class_get_method_from_name(ZMapClass,
309                                                                  ".ctor",
310                                                                  0);
311  mono_runtime_invoke(constructorMethod, res, NULL, exc);
312  map* sizeMap=getMap(m,"size");
313  while(m!=NULL){
314    void *values [2];
315    MonoString* name = mono_string_new(domain, m->name);
316    MonoString* value;
317    if(sizeMap!=NULL && strcasecmp(m->name,"value")==0)
318      value = mono_string_new_len(domain, m->value,atoi(sizeMap->value));
319    else
320      value = mono_string_new(domain, m->value);
321    values [0] = name;
322    values [1] = value;
323    mono_runtime_invoke(methods[3],res,values,exc);
324    m=m->next;
325  }
326  return res;
327}
328
329/**
330 * Create maps from ZMaps
331 * @param domain the Mono Domain
332 * @param classes the Mono classes required to create (_ZMapsClass,ZMapsClass,ZMapClass,KeysList)
333 * @param methods the Mono methods required (ZMapsGetMaps,ZMapsGetKeysCount,ZMapsGetKey,ZMapGetMap,ZMapGetKeysCount,ZMapGetKey,_ZMapsGetContent,_ZMapsGetChild)
334 * @param m the ZMaps to use as source to create a new maps
335 * @return MonoObject* to a new ZMaps
336 */
337maps* mapsFromZMaps(MonoDomain* domain,MonoClass **classes,MonoMethod **methods,MonoObject* m){
338  maps* res=NULL;
339  if(m!=NULL){
340    MonoObject *exc=NULL;
341    MonoObject *okeys = mono_runtime_invoke(methods[1],m,NULL,&exc);
342    if(exc!=NULL)
343      {
344        fprintf(stderr,"ERROR : %s\n", mono_string_to_utf8(mono_object_to_string(exc, NULL)));
345        fflush(stderr);
346        return res;
347      }
348
349    int keyCount=*(int*)mono_object_unbox (okeys);
350    for(int i=0;i<keyCount;i++){
351      void* values[1];
352      values[0]=&i;
353      exc=NULL;
354      MonoString *okey = (MonoString*) mono_runtime_invoke(methods[2],m,values,&exc);
355      char* key = mono_string_to_utf8(okey);
356      maps* tmp=createMaps(key);
357      values[0]=mono_string_new (domain, key);
358      MonoString *content_ZMaps = (MonoString*) mono_runtime_invoke(methods[0],m,values,&exc);
359      MonoObject *content = mono_runtime_invoke(methods[6],(MonoObject*)content_ZMaps,NULL,&exc);
360      tmp->content=mapFromZMap(domain,classes,methods,content);
361      MonoObject *childs = mono_runtime_invoke(methods[7],content_ZMaps,NULL,&exc);
362      tmp->child=mapsFromZMaps(domain,classes,methods,childs);
363      if(res==NULL){
364        res=dupMaps(&tmp);
365      }else
366        addMapsToMaps(&res,tmp);
367      freeMaps(&tmp);
368      free(tmp);
369      mono_free(key);
370    }
371  }
372  return res;
373}
374
375/**
376 * Create map from ZMap
377 * @param domain the Mono Domain
378 * @param classes the Mono classes required (_ZMapsClass,ZMapsClass,ZMapClass,KeysList)
379 * @param methods the Mono methods required (ZMapsGetMaps,ZMapsGetKeysCount,ZMapsGetKey,ZMapGetMap,ZMapGetKeysCount,ZMapGetKey,_ZMapsGetContent,_ZMapsGetChild,ZMapGetSize)
380 * @param m the ZMap to use as source to create a new map
381 * @return MonoObject* to a new ZMap
382 */
383map* mapFromZMap(MonoDomain* domain,MonoClass **classes,MonoMethod **methods,MonoObject* m){
384  map* res=NULL;
385  if(m!=NULL){
386    MonoObject *exc = NULL;
387    MonoObject *okeys = mono_runtime_invoke(methods[4],m,NULL,&exc);
388    int keyCount=*(int*)mono_object_unbox (okeys);
389    MonoObject *osize = mono_runtime_invoke(methods[8],m,NULL,&exc);
390    int size=*(int*)mono_object_unbox (osize);
391    for(int i=0;i<keyCount;i++){
392      void* values[1];
393      values[0]=&i;
394      exc=NULL;
395      MonoString *okey = (MonoString*) mono_runtime_invoke(methods[5],m,values,&exc);
396      char* key = mono_string_to_utf8(okey);
397      values[0]=mono_string_new (domain, key);
398      exc=NULL;
399      MonoString *ovalue = (MonoString*) mono_runtime_invoke(methods[3],m,values,&exc);
400      char* value = mono_string_to_utf8(ovalue);
401      if(res==NULL)
402        res=createMap(key,value);
403      else
404        addToMap(res,key,value);
405    }
406  }
407  return res;
408}
409
410/**
411 * The translate function to search in zoo-services gettext domain for translating a string.
412 * @param str the string to be translated
413 * @return the translated string
414 */
415static MonoString* MonoTranslate(MonoString *str){
416  return mono_string_new (mono_domain_get(), _(mono_string_to_utf8(str)));
417}
418
419/**
420 * The updateStatus function to update the ongoing status of a ZOO-Service.
421 * @param m the main.cfg map
422 * @param str the message for the current step
423 * @param p the percentage of the
424 * @return the translated string
425 */
426static void MonoUpdateStatus(MonoObject* obj, MonoString *str, int p) { 
427        MonoDomain* domain = mono_object_get_domain(obj);       
428        maps *confMaps = mapsFromZMaps(domain, iclasses, imethods, obj);       
429        setMapInMaps(confMaps, "lenv", "message", mono_string_to_utf8(str));   
430        int tmp = p > 100 || p < 0 ? -1 : p;   
431        char tmpStatus[5];
432        snprintf(tmpStatus, 4, "%d", tmp);     
433        setMapInMaps(confMaps, "lenv", "status", (char*)tmpStatus);     
434        _updateStatus(confMaps);       
435        freeMaps(&confMaps);   
436        free(confMaps);
437        return;
438}
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