source: xmlrpcnet/trunk/fuentes/src/XmlRpcServiceInfo.cs @ 379

Last change on this file since 379 was 379, checked in by hectorgh, 5 years ago

adding project files

File size: 13.5 KB
Line 
1/*
2XML-RPC.NET library
3Copyright (c) 2001-2006, Charles Cook <charlescook@cookcomputing.com>
4
5Permission is hereby granted, free of charge, to any person
6obtaining a copy of this software and associated documentation
7files (the "Software"), to deal in the Software without restriction,
8including without limitation the rights to use, copy, modify, merge,
9publish, distribute, sublicense, and/or sell copies of the Software,
10and to permit persons to whom the Software is furnished to do so,
11subject to the following conditions:
12
13The above copyright notice and this permission notice shall be
14included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23DEALINGS IN THE SOFTWARE.
24*/
25
26namespace CookComputing.XmlRpc
27{
28  using System;
29  using System.Collections;
30  using System.Collections.Generic;
31  using System.Reflection;
32  using System.Text.RegularExpressions;
33
34  public enum XmlRpcType
35  {
36    tInvalid,
37    tInt32,
38    tInt64,
39    tBoolean,
40    tString,
41    tDouble,
42    tDateTime,
43    tBase64,
44    tStruct,
45    tHashtable,
46    tArray,
47    tMultiDimArray,
48    tVoid
49  }
50
51  public class XmlRpcServiceInfo
52  {
53    public static XmlRpcServiceInfo CreateServiceInfo(Type type)
54    {
55      XmlRpcServiceInfo svcInfo = new XmlRpcServiceInfo();
56      // extract service info
57      XmlRpcServiceAttribute svcAttr = (XmlRpcServiceAttribute)
58        Attribute.GetCustomAttribute(type, typeof(XmlRpcServiceAttribute));
59      if (svcAttr != null && svcAttr.Description != "")
60        svcInfo.doc = svcAttr.Description;
61      if (svcAttr != null && svcAttr.Name != "")
62        svcInfo.Name = svcAttr.Name;
63      else
64        svcInfo.Name = type.Name;
65      // extract method info
66      Hashtable methods = new Hashtable();
67
68      foreach (Type itf in type.GetInterfaces())
69      {
70        XmlRpcServiceAttribute itfAttr = (XmlRpcServiceAttribute)
71          Attribute.GetCustomAttribute(itf, typeof(XmlRpcServiceAttribute));
72        if (itfAttr != null)
73          svcInfo.doc = itfAttr.Description;
74#if (!COMPACT_FRAMEWORK)
75        InterfaceMapping imap = type.GetInterfaceMap(itf);
76        foreach (MethodInfo mi in imap.InterfaceMethods)
77        {
78          ExtractMethodInfo(methods, mi, itf);
79        }
80#else
81        foreach (MethodInfo mi in itf.GetMethods())
82        {
83          ExtractMethodInfo(methods, mi, itf);
84        }
85#endif
86      }
87
88      foreach (MethodInfo mi in type.GetMethods())
89      {
90        ArrayList mthds = new ArrayList();
91        mthds.Add(mi);
92        MethodInfo curMi = mi;
93        while (true)
94        {
95          MethodInfo baseMi = curMi.GetBaseDefinition();
96          if (baseMi.DeclaringType == curMi.DeclaringType)
97            break;
98          mthds.Insert(0, baseMi);
99          curMi = baseMi;
100        }
101        foreach (MethodInfo mthd in mthds)
102        {
103          ExtractMethodInfo(methods, mthd, type);
104        }
105      }
106      svcInfo.methodInfos = new XmlRpcMethodInfo[methods.Count];
107      methods.Values.CopyTo(svcInfo.methodInfos, 0);
108      Array.Sort(svcInfo.methodInfos);
109      return svcInfo;
110    }
111
112    static void ExtractMethodInfo(Hashtable methods, MethodInfo mi, Type type)
113    {
114      XmlRpcMethodAttribute attr = (XmlRpcMethodAttribute)
115        Attribute.GetCustomAttribute(mi,
116        typeof(XmlRpcMethodAttribute));
117      if (attr == null)
118        return;
119      XmlRpcMethodInfo mthdInfo = new XmlRpcMethodInfo();
120      mthdInfo.MethodInfo = mi;
121      mthdInfo.XmlRpcName = GetXmlRpcMethodName(mi);
122      mthdInfo.MiName = mi.Name;
123      mthdInfo.Doc = attr.Description;
124      mthdInfo.IsHidden = attr.IntrospectionMethod | attr.Hidden;
125      // extract parameters information
126      ArrayList parmList = new ArrayList();
127      ParameterInfo[] parms = mi.GetParameters();
128      foreach (ParameterInfo parm in parms)
129      {
130        XmlRpcParameterInfo parmInfo = new XmlRpcParameterInfo();
131        parmInfo.Name = parm.Name;
132        parmInfo.Type = parm.ParameterType;
133        parmInfo.XmlRpcType = GetXmlRpcTypeString(parm.ParameterType);
134        // retrieve optional attributed info
135        parmInfo.Doc = "";
136        XmlRpcParameterAttribute pattr = (XmlRpcParameterAttribute)
137          Attribute.GetCustomAttribute(parm,
138          typeof(XmlRpcParameterAttribute));
139        if (pattr != null)
140        {
141          parmInfo.Doc = pattr.Description;
142          parmInfo.XmlRpcName = pattr.Name;
143        }
144        parmInfo.IsParams = Attribute.IsDefined(parm,
145          typeof(ParamArrayAttribute));
146        parmList.Add(parmInfo);
147      }
148      mthdInfo.Parameters = (XmlRpcParameterInfo[])
149        parmList.ToArray(typeof(XmlRpcParameterInfo));
150      // extract return type information
151      mthdInfo.ReturnType = mi.ReturnType;
152      mthdInfo.ReturnXmlRpcType = GetXmlRpcTypeString(mi.ReturnType);
153      object[] orattrs = mi.ReturnTypeCustomAttributes.GetCustomAttributes(
154        typeof(XmlRpcReturnValueAttribute), false);
155      if (orattrs.Length > 0)
156      {
157        mthdInfo.ReturnDoc = ((XmlRpcReturnValueAttribute)orattrs[0]).Description;
158      }
159
160      if (methods[mthdInfo.XmlRpcName] != null)
161      {
162        throw new XmlRpcDupXmlRpcMethodNames(String.Format("Method "
163          + "{0} in type {1} has duplicate XmlRpc method name {2}",
164          mi.Name, type.Name, mthdInfo.XmlRpcName));
165      }
166      else
167        methods.Add(mthdInfo.XmlRpcName, mthdInfo);
168    }
169
170    public MethodInfo GetMethodInfo(string xmlRpcMethodName)
171    {
172      foreach (XmlRpcMethodInfo xmi in methodInfos)
173      {
174        if (xmlRpcMethodName == xmi.XmlRpcName)
175        {
176          return xmi.MethodInfo;
177        }
178      }
179      return null;
180    }
181
182    static bool IsVisibleXmlRpcMethod(MethodInfo mi)
183    {
184      bool ret = false;
185      Attribute attr = Attribute.GetCustomAttribute(mi,
186        typeof(XmlRpcMethodAttribute));
187      if (attr != null)
188      {
189        XmlRpcMethodAttribute mattr = (XmlRpcMethodAttribute)attr;
190        ret = !(mattr.Hidden || mattr.IntrospectionMethod == true);
191      }
192      return ret;
193    }
194
195    public static string GetXmlRpcMethodName(MethodInfo mi)
196    {
197      XmlRpcMethodAttribute attr = (XmlRpcMethodAttribute)
198        Attribute.GetCustomAttribute(mi,
199        typeof(XmlRpcMethodAttribute));
200      if (attr != null
201        && attr.Method != null
202        && attr.Method != "")
203      {
204        return attr.Method;
205      }
206      else
207      {
208        return mi.Name;
209      }
210    }
211
212    public string GetMethodName(string XmlRpcMethodName)
213    {
214      foreach (XmlRpcMethodInfo methodInfo in methodInfos)
215      {
216        if (methodInfo.XmlRpcName == XmlRpcMethodName)
217          return methodInfo.MiName;
218      }
219      return null;
220    }
221
222    public String Doc
223    {
224      get { return doc; }
225      set { doc = value; }
226    }
227
228    public String Name
229    {
230      get { return name; }
231      set { name = value; }
232    }
233
234    public XmlRpcMethodInfo[] Methods
235    {
236      get { return methodInfos; }
237    }
238
239    public XmlRpcMethodInfo GetMethod(
240      String methodName)
241    {
242      foreach (XmlRpcMethodInfo mthdInfo in methodInfos)
243      {
244        if (mthdInfo.XmlRpcName == methodName)
245          return mthdInfo;
246      }
247      return null;
248    }
249
250    private XmlRpcServiceInfo()
251    {
252    }
253
254    public static XmlRpcType GetXmlRpcType(Type t)
255    {
256      return GetXmlRpcType(t, new Stack());
257    }
258
259    private static XmlRpcType GetXmlRpcType(Type t, Stack typeStack)
260    {
261      XmlRpcType ret;
262      if (t == typeof(Int32))
263        ret = XmlRpcType.tInt32;
264      else if (t == typeof(XmlRpcInt))
265        ret = XmlRpcType.tInt32;
266      else if (t == typeof(Int64))
267        ret = XmlRpcType.tInt64;
268      else if (t == typeof(Boolean))
269        ret = XmlRpcType.tBoolean;
270      else if (t == typeof(XmlRpcBoolean))
271        ret = XmlRpcType.tBoolean;
272      else if (t == typeof(String))
273        ret = XmlRpcType.tString;
274      else if (t == typeof(Double))
275        ret = XmlRpcType.tDouble;
276      else if (t == typeof(XmlRpcDouble))
277        ret = XmlRpcType.tDouble;
278      else if (t == typeof(DateTime))
279        ret = XmlRpcType.tDateTime;
280      else if (t == typeof(XmlRpcDateTime))
281        ret = XmlRpcType.tDateTime;
282      else if (t == typeof(byte[]))
283        ret = XmlRpcType.tBase64;
284      else if (t == typeof(XmlRpcStruct))
285      {
286        ret = XmlRpcType.tHashtable;
287      }
288      else if (t == typeof(Array))
289        ret = XmlRpcType.tArray;
290      else if (t.IsArray)
291      {
292#if (!COMPACT_FRAMEWORK)
293        Type elemType = t.GetElementType();
294        if (elemType != typeof(Object)
295          && GetXmlRpcType(elemType, typeStack) == XmlRpcType.tInvalid)
296        {
297          ret = XmlRpcType.tInvalid;
298        }
299        else
300        {
301          if (t.GetArrayRank() == 1)  // single dim array
302            ret = XmlRpcType.tArray;
303          else
304            ret = XmlRpcType.tMultiDimArray;
305        }
306#else
307        //!! check types of array elements if not Object[]
308        Type elemType = null;
309        string[] checkSingleDim = Regex.Split(t.FullName, "\\[\\]$");
310        if (checkSingleDim.Length > 1)  // single dim array
311        {
312          elemType = Type.GetType(checkSingleDim[0]);
313          ret = XmlRpcType.tArray;
314        }
315        else
316        {
317          string[] checkMultiDim = Regex.Split(t.FullName, "\\[,[,]*\\]$");
318          if (checkMultiDim.Length > 1)
319          {
320            elemType = Type.GetType(checkMultiDim[0]);
321            ret = XmlRpcType.tMultiDimArray;
322          }
323          else
324            ret = XmlRpcType.tInvalid;
325        }
326        if (elemType != null)
327        {
328          if (elemType != typeof(Object) 
329            && GetXmlRpcType(elemType, typeStack) == XmlRpcType.tInvalid)
330          {
331            ret = XmlRpcType.tInvalid;
332          }
333        }
334#endif
335
336      }
337#if !FX1_0
338      else if (t == typeof(int?))
339        ret = XmlRpcType.tInt32;
340      else if (t == typeof(long?))
341        ret = XmlRpcType.tInt64;
342      else if (t == typeof(Boolean?))
343        ret = XmlRpcType.tBoolean;
344      else if (t == typeof(Double?))
345        ret = XmlRpcType.tDouble;
346      else if (t == typeof(DateTime?))
347        ret = XmlRpcType.tDateTime;
348#endif
349      else if (t == typeof(void))
350      {
351        ret = XmlRpcType.tVoid;
352      }
353      else if ((t.IsValueType && !t.IsPrimitive && !t.IsEnum)
354        || t.IsClass)
355      {
356        // if type is struct or class its only valid for XML-RPC mapping if all
357        // its members have a valid mapping or are of type object which
358        // maps to any XML-RPC type
359        MemberInfo[] mis = t.GetMembers();
360        foreach (MemberInfo mi in mis)
361        {
362          if (mi.MemberType == MemberTypes.Field)
363          {
364            FieldInfo fi = (FieldInfo)mi;
365            if (typeStack.Contains(fi.FieldType))
366              continue;
367            try
368            {
369              typeStack.Push(fi.FieldType);
370              if ((fi.FieldType != typeof(Object)
371                && GetXmlRpcType(fi.FieldType, typeStack) == XmlRpcType.tInvalid))
372              {
373                return XmlRpcType.tInvalid;
374              }
375            }
376            finally
377            {
378              typeStack.Pop();
379            }
380          }
381          else if (mi.MemberType == MemberTypes.Property)
382          {
383            PropertyInfo pi = (PropertyInfo)mi;
384            if (typeStack.Contains(pi.PropertyType))
385              continue;
386            try
387            {
388              typeStack.Push(pi.PropertyType);
389              if ((pi.PropertyType != typeof(Object)
390                && GetXmlRpcType(pi.PropertyType, typeStack) == XmlRpcType.tInvalid))
391              {
392                return XmlRpcType.tInvalid;
393              }
394            }
395            finally
396            {
397              typeStack.Pop();
398            }
399          }
400        }
401        ret = XmlRpcType.tStruct;
402      }
403      else
404        ret = XmlRpcType.tInvalid;
405      return ret;
406    }
407
408    static public string GetXmlRpcTypeString(Type t)
409    {
410      XmlRpcType rpcType = GetXmlRpcType(t);
411      return GetXmlRpcTypeString(rpcType);
412    }
413
414    static public string GetXmlRpcTypeString(XmlRpcType t)
415    {
416      string ret = null;
417      if (t == XmlRpcType.tInt32)
418        ret = "integer";
419      else if (t == XmlRpcType.tInt64)
420        ret = "i8";
421      else if (t == XmlRpcType.tBoolean)
422        ret = "boolean";
423      else if (t == XmlRpcType.tString)
424        ret = "string";
425      else if (t == XmlRpcType.tDouble)
426        ret = "double";
427      else if (t == XmlRpcType.tDateTime)
428        ret = "dateTime";
429      else if (t == XmlRpcType.tBase64)
430        ret = "base64";
431      else if (t == XmlRpcType.tStruct)
432        ret = "struct";
433      else if (t == XmlRpcType.tHashtable)
434        ret = "struct";
435      else if (t == XmlRpcType.tArray)
436        ret = "array";
437      else if (t == XmlRpcType.tMultiDimArray)
438        ret = "array";
439      else if (t == XmlRpcType.tVoid)
440        ret = "void";
441      else
442        ret = null;
443      return ret;
444    }
445
446    XmlRpcMethodInfo[] methodInfos;
447    String doc;
448    string name;
449  }
450}
Note: See TracBrowser for help on using the repository browser.