source: trunk/zoo-project/zoo-kernel/service_internal_mono.c @ 975

Last change on this file since 975 was 917, checked in by djay, 5 years ago

Merge prototype-v0 branch in trunk

  • 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

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