aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/XmlRpcCS/XmlRpcSystemObject.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--XmlRpcCS/XmlRpcSystemObject.cs252
1 files changed, 252 insertions, 0 deletions
diff --git a/XmlRpcCS/XmlRpcSystemObject.cs b/XmlRpcCS/XmlRpcSystemObject.cs
new file mode 100644
index 0000000..5f79951
--- /dev/null
+++ b/XmlRpcCS/XmlRpcSystemObject.cs
@@ -0,0 +1,252 @@
1namespace Nwc.XmlRpc
2{
3 using System;
4 using System.Collections;
5 using System.Reflection;
6
7 /// <summary> XML-RPC System object implementation of extended specifications.</summary>
8 [XmlRpcExposed]
9 public class XmlRpcSystemObject
10 {
11 private XmlRpcServer _server;
12 static private IDictionary _methodHelp = new Hashtable();
13
14 /// <summary>Static <c>IDictionary</c> to hold mappings of method name to associated documentation String</summary>
15 static public IDictionary MethodHelp
16 {
17 get { return _methodHelp; }
18 }
19
20 /// <summary>Constructor.</summary>
21 /// <param name="server"><c>XmlRpcServer</c> server to be the system object for.</param>
22 public XmlRpcSystemObject(XmlRpcServer server)
23 {
24 _server = server;
25 server.Add("system", this);
26 _methodHelp.Add(this.GetType().FullName + ".methodHelp", "Return a string description.");
27 }
28
29 /// <summary>Invoke a method on a given object.</summary>
30 /// <remarks>Using reflection, and respecting the <c>XmlRpcExposed</c> attribute,
31 /// invoke the <paramref>methodName</paramref> method on the <paramref>target</paramref>
32 /// instance with the <paramref>parameters</paramref> provided. All this packages other <c>Invoke</c> methods
33 /// end up calling this.</remarks>
34 /// <returns><c>Object</c> the value the invoked method returns.</returns>
35 /// <exception cref="XmlRpcException">If method does not exist, is not exposed, parameters invalid, or invocation
36 /// results in an exception. Note, the <c>XmlRpcException.Code</c> will indicate cause.</exception>
37 static public Object Invoke(Object target, String methodName, IList parameters)
38 {
39 if (target == null)
40 throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
41 XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Invalid target object.");
42
43 Type type = target.GetType();
44 MethodInfo method = type.GetMethod(methodName);
45
46 try
47 {
48 if (!XmlRpcExposedAttribute.ExposedMethod(target, methodName))
49 throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
50 XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Method " + methodName + " is not exposed.");
51 }
52 catch (MissingMethodException me)
53 {
54 throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
55 XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": " + me.Message);
56 }
57
58 Object[] args = new Object[parameters.Count];
59
60 int index = 0;
61 foreach (Object arg in parameters)
62 {
63 args[index] = arg;
64 index++;
65 }
66
67 try
68 {
69 Object retValue = method.Invoke(target, args);
70 if (retValue == null)
71 throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
72 XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": Method returned NULL.");
73 return retValue;
74 }
75 catch (XmlRpcException e)
76 {
77 throw e;
78 }
79 catch (ArgumentException ae)
80 {
81 Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + ae.Message,
82 LogLevel.Information);
83 String call = methodName + "( ";
84 foreach (Object o in args)
85 {
86 call += o.GetType().Name;
87 call += " ";
88 }
89 call += ")";
90 throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
91 XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement type mismatch invoking " + call);
92 }
93 catch (TargetParameterCountException tpce)
94 {
95 Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + tpce.Message,
96 LogLevel.Information);
97 throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
98 XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement count mismatch invoking " + methodName);
99 }
100 catch (TargetInvocationException tie)
101 {
102 throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
103 XmlRpcErrorCodes.APPLICATION_ERROR_MSG + " Invoked method " + methodName + ": " + tie.Message);
104 }
105 }
106
107 /// <summary>List methods available on all handlers of this server.</summary>
108 /// <returns><c>IList</c> An array of <c>Strings</c>, each <c>String</c> will have form "object.method".</returns>
109 [XmlRpcExposed]
110 public IList listMethods()
111 {
112 IList methods = new ArrayList();
113 Boolean considerExposure;
114
115 foreach (DictionaryEntry handlerEntry in _server)
116 {
117 considerExposure = XmlRpcExposedAttribute.IsExposed(handlerEntry.Value.GetType());
118
119 foreach (MemberInfo mi in handlerEntry.Value.GetType().GetMembers())
120 {
121 if (mi.MemberType != MemberTypes.Method)
122 continue;
123
124 if (!((MethodInfo)mi).IsPublic)
125 continue;
126
127 if (considerExposure && !XmlRpcExposedAttribute.IsExposed(mi))
128 continue;
129
130 methods.Add(handlerEntry.Key + "." + mi.Name);
131 }
132 }
133
134 return methods;
135 }
136
137 /// <summary>Given a method name return the possible signatures for it.</summary>
138 /// <param name="name"><c>String</c> The object.method name to look up.</param>
139 /// <returns><c>IList</c> Of arrays of signatures.</returns>
140 [XmlRpcExposed]
141 public IList methodSignature(String name)
142 {
143 IList signatures = new ArrayList();
144 int index = name.IndexOf('.');
145
146 if (index < 0)
147 return signatures;
148
149 String oName = name.Substring(0, index);
150 Object obj = _server[oName];
151
152 if (obj == null)
153 return signatures;
154
155 MemberInfo[] mi = obj.GetType().GetMember(name.Substring(index + 1));
156
157 if (mi == null || mi.Length != 1) // for now we want a single signature
158 return signatures;
159
160 MethodInfo method;
161
162 try
163 {
164 method = (MethodInfo)mi[0];
165 }
166 catch (Exception e)
167 {
168 Logger.WriteEntry("Attempted methodSignature call on " + mi[0] + " caused: " + e,
169 LogLevel.Information);
170 return signatures;
171 }
172
173 if (!method.IsPublic)
174 return signatures;
175
176 IList signature = new ArrayList();
177 signature.Add(method.ReturnType.Name);
178
179 foreach (ParameterInfo param in method.GetParameters())
180 {
181 signature.Add(param.ParameterType.Name);
182 }
183
184
185 signatures.Add(signature);
186
187 return signatures;
188 }
189
190 /// <summary>Help for given method signature. Not implemented yet.</summary>
191 /// <param name="name"><c>String</c> The object.method name to look up.</param>
192 /// <returns><c>String</c> help text. Rich HTML text.</returns>
193 [XmlRpcExposed]
194 public String methodHelp(String name)
195 {
196 String help = null;
197
198 try
199 {
200 help = (String)_methodHelp[_server.MethodName(name)];
201 }
202 catch (XmlRpcException e)
203 {
204 throw e;
205 }
206 catch (Exception) { /* ignored */ };
207
208 if (help == null)
209 help = "No help available for: " + name;
210
211 return help;
212 }
213
214 /// <summary>Boxcarring support method.</summary>
215 /// <param name="calls"><c>IList</c> of calls</param>
216 /// <returns><c>ArrayList</c> of results/faults.</returns>
217 [XmlRpcExposed]
218 public IList multiCall(IList calls)
219 {
220 IList responses = new ArrayList();
221 XmlRpcResponse fault = new XmlRpcResponse();
222
223 foreach (IDictionary call in calls)
224 {
225 try
226 {
227 XmlRpcRequest req = new XmlRpcRequest((String)call[XmlRpcXmlTokens.METHOD_NAME],
228 (ArrayList)call[XmlRpcXmlTokens.PARAMS]);
229 Object results = _server.Invoke(req);
230 IList response = new ArrayList();
231 response.Add(results);
232 responses.Add(response);
233 }
234 catch (XmlRpcException e)
235 {
236 fault.SetFault(e.FaultCode, e.FaultString);
237 responses.Add(fault.Value);
238 }
239 catch (Exception e2)
240 {
241 fault.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
242 XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
243 responses.Add(fault.Value);
244 }
245 }
246
247 return responses;
248 }
249
250 }
251}
252