// /** // * File: JsonCallResource.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using System.Reflection; using System.Collections.Generic; using ln.http.exceptions; using ln.logging; using System.Linq; using System.Diagnostics; using ln.json.mapping; using ln.json; namespace ln.http.resources { public class CallableAttribute : Attribute { public String Alias { get; set; } } public abstract class JsonCallResource : BaseResource { Dictionary callableMethods = new Dictionary(); Dictionary methodResources = new Dictionary(); public JsonCallResource(Resource container, string name) : base(container, name) { initialize(); } private void initialize() { Dictionary> callables = new Dictionary>(); foreach (MethodInfo methodInfo in this.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { CallableAttribute callableAttribute = methodInfo.GetCustomAttribute(); if (callableAttribute != null) { string alias = callableAttribute.Alias == null ? methodInfo.Name : callableAttribute.Alias; if (!callables.ContainsKey(alias)) { callables.Add(alias, new List()); } callables[alias].Add(methodInfo); } } foreach (String alias in callables.Keys) { callableMethods.Add(alias, callables[alias].ToArray()); new MethodResource(this, alias); } foreach (PropertyInfo propertyInfo in this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (propertyInfo.GetCustomAttribute() != null) { new CallableProperty(this, propertyInfo); } } } private object InvokeMethodCall(string methodName, object[] arguments) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); MethodInfo methodInfo = FindMethodSignature(methodName, arguments.Length); object result = methodInfo.Invoke(this, arguments); stopwatch.Stop(); Logging.Log(LogLevel.DEBUGDETAIL,"InvokeMethodCall({0},...): {1}ms",methodName,stopwatch.ElapsedMilliseconds); return result; } private object InvokeMethodCall(string methodName, KeyValuePair[] arguments) { MethodInfo methodInfo = FindMethodSignature(methodName, arguments.Select((kvp) => kvp.Key).ToArray()); Dictionary args = new Dictionary(); foreach (KeyValuePair kvp in arguments) args.Add(kvp.Key, kvp.Value); ParameterInfo[] parameterInfos = methodInfo.GetParameters(); object[] pl = new object[parameterInfos.Length]; for (int n=0;n(httpRequest.ContentReader.ReadToEnd()); MethodResult methodResult; try { methodResult = new MethodResult(); methodResult.MethodName = methodCall.MethodName; methodResult.Result = InvokeMethodCall(methodCall.MethodName, methodCall.Parameters); } catch (Exception e) { methodResult = new MethodResult(); methodResult.MethodName = methodCall.MethodName; methodResult.Exception = e; Logging.Log(LogLevel.ERROR, "JsonCallResource: method call caught exception: {0}",e); Logging.Log(e); } String result = JSONMapper.DefaultMapper.ToJson(methodResult).ToString(); HttpResponse httpResponse = new HttpResponse(httpRequest); httpResponse.SetHeader("content-type", "application/json"); httpResponse.ContentWriter.Write(result); return httpResponse; } private string SerializeResult(MethodInfo methodInfo,MethodResult methodResult) { if (methodResult.Exception != null) { return JSONMapper.DefaultMapper.ToJson(methodResult).ToString(); } else { return FlatSerializeResult(methodResult); } } private string FlatSerializeResult(MethodResult methodResult) { JSONObject jMethodResult = new JSONObject(); jMethodResult.Add("Exception", null); jMethodResult.Add("MethodName", methodResult.MethodName); JSONObject jResult = new JSONObject(); jMethodResult.Add("Result", jResult); Type type = methodResult.GetType(); foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) { Type fType = fieldInfo.FieldType; if ((fType.IsValueType) || (typeof(string).Equals(fType)) || (fType.IsArray)) { jResult.Add(fieldInfo.Name, fieldInfo.GetValue(methodResult.Result)); } else { jResult.Add(fieldInfo.Name, fieldInfo.GetValue(methodResult.Result).ToString()); } } return jMethodResult.ToString(); } class MethodCall { public String MethodName; public object[] Parameters; } class MethodResult { public String MethodName; public object Result; public Exception Exception; } class MethodResource : Resource { public MethodResource(JsonCallResource container,String methodName) :base(container,methodName) { } public override HttpResponse GetResponse(HttpRequest httpRequest) { throw new NotImplementedException(); } public override void AddResource(Resource resource) => throw new NotImplementedException(); public override bool Contains(string name) => throw new NotImplementedException(); public override IEnumerable GetResources() => throw new NotImplementedException(); public override void RemoveResource(Resource resource) => throw new NotImplementedException(); } class CallableProperty : Resource { public CallableProperty(JsonCallResource container, PropertyInfo propertyInfo) : base(container, propertyInfo.Name) { this.propertyInfo = propertyInfo; } PropertyInfo propertyInfo; public override void AddResource(Resource resource) => throw new NotImplementedException(); public override void RemoveResource(Resource resource) => throw new NotImplementedException(); public override bool Contains(string name) => false; public override IEnumerable GetResources() => new Resource[0]; public override HttpResponse GetResponse(HttpRequest httpRequest) { try { object v = propertyInfo.GetValue(Container); String result = JSONMapper.DefaultMapper.ToJson(v).ToString(); HttpResponse httpResponse = new HttpResponse(httpRequest); httpResponse.SetHeader("content-type", "application/json"); httpResponse.ContentWriter.Write(result); return httpResponse; } catch (Exception e) { Logging.Log(e); HttpResponse httpResponse = new HttpResponse(httpRequest); httpResponse.StatusCode = 500; return httpResponse; } } } } }