Reorganisation of the source tree
[ghc-hetmet.git] / rts / dotnet / Invoker.cpp
1 //
2 // (c) 2002-2003, sof.
3 //
4 // Dynamic invocation helper classes. The details of how
5 // to access the .NET object model via the Reflection API
6 // is taken care of by Invoker.{h,cpp}
7 //
8 #include "Invoker.h"
9
10 namespace DynInvoke {
11
12 static TypeName* ParseType(String* str) {
13     int curPos = 0;
14     int endPos;
15
16     //    Console::WriteLine("x{0}y", str);
17     TypeName* typeName = new TypeName();
18
19     if ( str->get_Chars(0) == '[' ) {
20       endPos = str->IndexOf(']');
21       curPos = endPos + 1;
22       typeName->m_assembly = str->Substring(1,endPos-1);
23       typeName->m_length = endPos+1;
24     }
25     String* delimStr = " ,()";
26     Char delims __gc [] = delimStr->ToCharArray();
27
28     endPos  = str->IndexOfAny(delims,curPos);
29     //    Console::WriteLine("{0} {1} x{2}x", __box(endPos), __box(curPos), str);
30     if ( endPos == -1 ) {
31       typeName->m_class = str->Substring(curPos);
32     } else {
33       typeName->m_class = str->Substring(curPos,endPos-curPos);
34     }
35
36     //    typeName->m_class = str->Substring(curPos,endPos-curPos);
37     typeName->m_length += endPos-curPos;
38
39     return typeName;
40 }
41
42 // Method: GetType(String* typeName);
43 // 
44 // Purpose: Assembly-savvy version of Type::GetType()
45 //
46 Type* InvokeBridge::GetType(String* typeName) {
47
48   try {
49     Type* t = Type::GetType(typeName);
50     if (t) return t;
51   } catch (Exception*) {
52     ;
53   }
54
55   for (int i=0;i < InvokeBridge::m_assemblies->Count; i++) {
56      try {
57        String* stuff = String::Format("{0},{1}",typeName,InvokeBridge::m_assemblies->get_Item(i)->ToString());
58        //       Console::WriteLine(stuff);
59        Type* t = Type::GetType(stuff);
60        if (t) {
61          return t;
62        }
63      } catch (Exception*) {
64        continue;
65      }
66   }
67   return 0;
68 }
69
70 //
71 // Method:  CreateInstance(String* typeName, Object* [])
72 //
73 // Purpose: Assembly-savvy invocation of Activator::CreateInstance
74 Object* InvokeBridge::CreateInstance(TypeName* typeName,
75                                      Object* args[]) {
76
77   Object* instance = 0;
78   Type*   t = InvokeBridge::GetType(typeName->toStdString());
79
80   //  Console::WriteLine("x{0} y{1}", typeName->toStdString(), t);
81   if (!t) {
82     try {
83       Assembly* localA = Assembly::LoadFrom(typeName->m_assembly);
84       t = localA->GetType(typeName->m_class);
85     } catch (Exception* e) {
86       ;
87     }
88   }
89   
90   if (!t) {
91     try {
92       AppDomain* currentDomain = AppDomain::CurrentDomain;
93       
94       //      Assembly* stuff[] = currentDomain->GetAssemblies();
95       //      for (int i=0;i < stuff.Length; i++) {
96       //        Console::WriteLine("x{0} y{1}", stuff[i]->ToString(), stuff[i]->FullName);
97       //      }
98       //      Console::WriteLine("x{0} y{1}", typeName->toStdString(), t);
99       Assembly* localA = Assembly::LoadWithPartialName("HugsAssembly");
100       t = localA->GetType(typeName->m_class);
101       //      Console::WriteLine("x{0} y{1}", typeName->toStdString(), t);
102     } catch (Exception*) {
103       ;
104     }
105   }
106
107   if (t) {
108     try {
109       Object* o =Activator::CreateInstance(t,(Object* [])args);
110       return o;
111     } catch (Exception* e) {
112       Console::WriteLine("Failure: {0}", e);
113       return 0;
114     }
115   }
116 }
117
118 //
119 // Method: CreateObject(String* objSpec, Object* args[])
120 //
121 // Purpose: Given a fully qualified name of a class/type, try
122 //          to create an instance of it.
123 //
124 Object* InvokeBridge::CreateObject(String* assemName,
125                                    String* objSpec,
126                                    Object* args[]) {
127  
128   Object* instance = 0;
129
130   // Unravel the name of the class/type.
131   TypeName* typeName = ParseType(objSpec);
132   
133   if (assemName != 0 && assemName->Length > 0) {
134     typeName->m_assembly = assemName;
135   }
136
137   // Try creating the instance..
138   try {
139     instance = InvokeBridge::CreateInstance(typeName,(Object* [])args);
140   } catch (Exception* e) {
141     Console::WriteLine("Unable to create instance \"{0}\" {1}", objSpec, e);
142     throw(e);
143   }
144   if (!instance) {
145     Console::WriteLine("Unable to create instance \"{0}\"", objSpec);
146   }
147   return instance;
148 }
149
150 //
151 // Method:  InvokeMethod
152 // 
153 // Purpose: Given a pointer to an already created object, look up
154 //          one of its method. If found, invoke the method passing it
155 //          'args' as arguments.
156 //
157 Object*
158 InvokeBridge::InvokeMethod(Object* obj, 
159                            String* methName,
160                            Object* args[]) {
161   // Get the methods from the type
162   MethodInfo* methods __gc[] = obj->GetType()->GetMethods();
163   MethodInfo* mInfo;
164
165   if (!methods) {
166     Console::WriteLine("InvokeMethod: No matching types found");
167     return 0;
168   }
169                         
170   System::Reflection::BindingFlags flgs 
171     = (System::Reflection::BindingFlags) // why do I need to cast?
172       (System::Reflection::BindingFlags::Public       |
173        System::Reflection::BindingFlags::NonPublic    |
174        System::Reflection::BindingFlags::Instance     |
175        System::Reflection::BindingFlags::Static       |
176        System::Reflection::BindingFlags::InvokeMethod);
177     
178   /* Caller is assumed to catch any exceptions raised. */
179   return obj->GetType()->InvokeMember(methName,
180                                       flgs,
181                                       0,
182                                       obj,
183                                       (Object __gc* [])args);
184 }
185
186 //
187 // Method:  InvokeStaticMethod
188 // 
189 // Purpose: Invoke a static method, given the fully qualified name
190 //          of the method (and its arguments). If found, invoke the
191 //          method passing it 'args' as arguments.
192 //
193 Object* InvokeBridge::InvokeStaticMethod(String* assemName,
194                                          String* typeAndMethName,
195                                          Object* args[]) {
196
197   // Get the methods from the type
198   MethodInfo* methods __gc[];
199   MethodInfo* mInfo;
200
201   int lastDot = typeAndMethName->LastIndexOf('.');
202   String* className = typeAndMethName->Substring(0,lastDot);
203   String* methName  = typeAndMethName->Substring(lastDot+1);
204
205   // Unravel the name of the class/type.
206   TypeName* typeName = ParseType(className);
207   Type* t;
208   
209   if (assemName != 0 && assemName->Length > 0) {
210     typeName->m_assembly = assemName;
211   }
212   
213   try {
214     t = InvokeBridge::GetType(typeName->toStdString());
215     
216     if (!t) {
217       try {
218         Assembly* localA = Assembly::LoadFrom(typeName->m_assembly);
219         t = localA->GetType(typeName->m_class);
220         //      Console::WriteLine("InvokeStaticMethod: Type {0} found", t);
221       } catch (Exception* e) {
222         ;
223       }
224     }
225
226     if (t) {
227       methods = t->GetMethods();
228     } else {
229       Console::WriteLine("InvokeStaticMethod: Type {0} not found", className);
230       return 0;
231     }
232   } catch (Exception *e) {
233       Console::WriteLine("InvokeStaticMethod: Type {0} not found", className);
234       throw(e);
235   }
236
237   System::Reflection::BindingFlags flgs 
238     = (System::Reflection::BindingFlags) // why do I need to cast?
239       (System::Reflection::BindingFlags::DeclaredOnly |
240        System::Reflection::BindingFlags::Public       |
241        System::Reflection::BindingFlags::NonPublic    |
242        System::Reflection::BindingFlags::Static       |
243        System::Reflection::BindingFlags::InvokeMethod);
244     
245   return t->InvokeMember(methName,
246                          flgs,
247                          0,
248                          0,
249                          (Object __gc* [])args);
250 }
251
252 //
253 // Method:  GetField
254 //
255 // Purpose: Fetch the (boxed) value of named field of a given object.
256 //
257 Object* InvokeBridge::GetField(Object* obj, System::String* fieldName) {
258
259   FieldInfo* fInfo = obj->GetType()->GetField(fieldName);
260   return fInfo->GetValue(obj);
261 }
262
263 //
264 // Method:  GetStaticField
265 //
266 // Purpose: Fetch the (boxed) value of named static field.
267 //
268 Object* InvokeBridge::GetStaticField(System::String* clsName,
269                                      System::String* fieldName) {
270
271   Type* ty = InvokeBridge::GetType(clsName);
272   System::Reflection::BindingFlags static_field_flgs 
273     = (System::Reflection::BindingFlags)
274     (System::Reflection::BindingFlags::Public       |
275      System::Reflection::BindingFlags::NonPublic    |
276      System::Reflection::BindingFlags::FlattenHierarchy |
277      System::Reflection::BindingFlags::Static);
278
279   FieldInfo* fInfo = ty->GetField(fieldName, static_field_flgs);
280   return fInfo->GetValue(0); // according to doc, ok to pass any val here.
281 }
282
283 //
284 // Method:  SetField
285 //
286 // Purpose: Replace the (boxed) value of named field of a given object.
287 //
288 void InvokeBridge::SetField(Object* obj, System::String* fieldName, Object* val) {
289
290   FieldInfo* fInfo = obj->GetType()->GetField(fieldName);
291   fInfo->SetValue(obj,val);
292   return;
293 }
294
295 //
296 // Method:  SetStaticField
297 //
298 // Purpose: Replace the (boxed) value of named static field.
299 //
300 void InvokeBridge::SetStaticField(System::String* clsName,
301                                   System::String* fieldName,
302                                   Object* val) {
303
304   Type* ty = InvokeBridge::GetType(clsName);
305   System::Reflection::BindingFlags static_field_flgs 
306     = (System::Reflection::BindingFlags)
307     (System::Reflection::BindingFlags::Public       |
308      System::Reflection::BindingFlags::NonPublic    |
309      System::Reflection::BindingFlags::FlattenHierarchy |
310      System::Reflection::BindingFlags::Static);
311   
312   FieldInfo* fInfo = ty->GetField(fieldName,static_field_flgs);
313   fInfo->SetValue(0,val);
314   return;
315 }
316
317 Object* InvokeBridge::NewString(System::String* s)
318 {
319   System::String* c = System::String::Copy(s);
320   return dynamic_cast<Object*>(c);
321 }
322
323 Array* InvokeBridge::NewArgArray(int sz)
324 {
325  return Array::CreateInstance(__typeof(Object), sz); 
326 }
327
328 void InvokeBridge::SetArg(Object* arr[], Object* val, int idx)
329 {
330  arr->SetValue(val,idx);
331 }
332
333 Object* InvokeBridge::GetArg(Object* arr[], int idx)
334 {
335  return arr->GetValue(idx);
336 }
337
338 } /* namespace */