From f95b6081cba084d1b067acea99c0effa2b3bf42c Mon Sep 17 00:00:00 2001 From: MW Date: Thu, 24 May 2007 12:35:32 +0000 Subject: Renamed the new Directories. (removed the "-Source" from the end of them) --- Common/XmlRpcCS/XmlRpcSystemObject.cs | 252 ++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 Common/XmlRpcCS/XmlRpcSystemObject.cs (limited to 'Common/XmlRpcCS/XmlRpcSystemObject.cs') diff --git a/Common/XmlRpcCS/XmlRpcSystemObject.cs b/Common/XmlRpcCS/XmlRpcSystemObject.cs new file mode 100644 index 0000000..5f79951 --- /dev/null +++ b/Common/XmlRpcCS/XmlRpcSystemObject.cs @@ -0,0 +1,252 @@ +namespace Nwc.XmlRpc +{ + using System; + using System.Collections; + using System.Reflection; + + /// XML-RPC System object implementation of extended specifications. + [XmlRpcExposed] + public class XmlRpcSystemObject + { + private XmlRpcServer _server; + static private IDictionary _methodHelp = new Hashtable(); + + /// Static IDictionary to hold mappings of method name to associated documentation String + static public IDictionary MethodHelp + { + get { return _methodHelp; } + } + + /// Constructor. + /// XmlRpcServer server to be the system object for. + public XmlRpcSystemObject(XmlRpcServer server) + { + _server = server; + server.Add("system", this); + _methodHelp.Add(this.GetType().FullName + ".methodHelp", "Return a string description."); + } + + /// Invoke a method on a given object. + /// Using reflection, and respecting the XmlRpcExposed attribute, + /// invoke the methodName method on the target + /// instance with the parameters provided. All this packages other Invoke methods + /// end up calling this. + /// Object the value the invoked method returns. + /// If method does not exist, is not exposed, parameters invalid, or invocation + /// results in an exception. Note, the XmlRpcException.Code will indicate cause. + static public Object Invoke(Object target, String methodName, IList parameters) + { + if (target == null) + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD, + XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Invalid target object."); + + Type type = target.GetType(); + MethodInfo method = type.GetMethod(methodName); + + try + { + if (!XmlRpcExposedAttribute.ExposedMethod(target, methodName)) + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD, + XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Method " + methodName + " is not exposed."); + } + catch (MissingMethodException me) + { + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD, + XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": " + me.Message); + } + + Object[] args = new Object[parameters.Count]; + + int index = 0; + foreach (Object arg in parameters) + { + args[index] = arg; + index++; + } + + try + { + Object retValue = method.Invoke(target, args); + if (retValue == null) + throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR, + XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": Method returned NULL."); + return retValue; + } + catch (XmlRpcException e) + { + throw e; + } + catch (ArgumentException ae) + { + Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + ae.Message, + LogLevel.Information); + String call = methodName + "( "; + foreach (Object o in args) + { + call += o.GetType().Name; + call += " "; + } + call += ")"; + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS, + XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement type mismatch invoking " + call); + } + catch (TargetParameterCountException tpce) + { + Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + tpce.Message, + LogLevel.Information); + throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS, + XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement count mismatch invoking " + methodName); + } + catch (TargetInvocationException tie) + { + throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR, + XmlRpcErrorCodes.APPLICATION_ERROR_MSG + " Invoked method " + methodName + ": " + tie.Message); + } + } + + /// List methods available on all handlers of this server. + /// IList An array of Strings, each String will have form "object.method". + [XmlRpcExposed] + public IList listMethods() + { + IList methods = new ArrayList(); + Boolean considerExposure; + + foreach (DictionaryEntry handlerEntry in _server) + { + considerExposure = XmlRpcExposedAttribute.IsExposed(handlerEntry.Value.GetType()); + + foreach (MemberInfo mi in handlerEntry.Value.GetType().GetMembers()) + { + if (mi.MemberType != MemberTypes.Method) + continue; + + if (!((MethodInfo)mi).IsPublic) + continue; + + if (considerExposure && !XmlRpcExposedAttribute.IsExposed(mi)) + continue; + + methods.Add(handlerEntry.Key + "." + mi.Name); + } + } + + return methods; + } + + /// Given a method name return the possible signatures for it. + /// String The object.method name to look up. + /// IList Of arrays of signatures. + [XmlRpcExposed] + public IList methodSignature(String name) + { + IList signatures = new ArrayList(); + int index = name.IndexOf('.'); + + if (index < 0) + return signatures; + + String oName = name.Substring(0, index); + Object obj = _server[oName]; + + if (obj == null) + return signatures; + + MemberInfo[] mi = obj.GetType().GetMember(name.Substring(index + 1)); + + if (mi == null || mi.Length != 1) // for now we want a single signature + return signatures; + + MethodInfo method; + + try + { + method = (MethodInfo)mi[0]; + } + catch (Exception e) + { + Logger.WriteEntry("Attempted methodSignature call on " + mi[0] + " caused: " + e, + LogLevel.Information); + return signatures; + } + + if (!method.IsPublic) + return signatures; + + IList signature = new ArrayList(); + signature.Add(method.ReturnType.Name); + + foreach (ParameterInfo param in method.GetParameters()) + { + signature.Add(param.ParameterType.Name); + } + + + signatures.Add(signature); + + return signatures; + } + + /// Help for given method signature. Not implemented yet. + /// String The object.method name to look up. + /// String help text. Rich HTML text. + [XmlRpcExposed] + public String methodHelp(String name) + { + String help = null; + + try + { + help = (String)_methodHelp[_server.MethodName(name)]; + } + catch (XmlRpcException e) + { + throw e; + } + catch (Exception) { /* ignored */ }; + + if (help == null) + help = "No help available for: " + name; + + return help; + } + + /// Boxcarring support method. + /// IList of calls + /// ArrayList of results/faults. + [XmlRpcExposed] + public IList multiCall(IList calls) + { + IList responses = new ArrayList(); + XmlRpcResponse fault = new XmlRpcResponse(); + + foreach (IDictionary call in calls) + { + try + { + XmlRpcRequest req = new XmlRpcRequest((String)call[XmlRpcXmlTokens.METHOD_NAME], + (ArrayList)call[XmlRpcXmlTokens.PARAMS]); + Object results = _server.Invoke(req); + IList response = new ArrayList(); + response.Add(results); + responses.Add(response); + } + catch (XmlRpcException e) + { + fault.SetFault(e.FaultCode, e.FaultString); + responses.Add(fault.Value); + } + catch (Exception e2) + { + fault.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR, + XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message); + responses.Add(fault.Value); + } + } + + return responses; + } + + } +} + -- cgit v1.1