From f4c5df07c1441d653de8a3ca554c3f0e694ca1fa Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Tue, 3 Mar 2020 17:07:03 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 4 ++ HTTPRequestExtensions.cs | 21 +++++++ HttpObjectContainer.cs | 43 ++++++++++++++ HttpObjectMapper.cs | 22 ++++++++ IObjectHandler.cs | 11 ++++ MappingContainer.cs | 103 ++++++++++++++++++++++++++++++++++ ObjectHandler.cs | 56 ++++++++++++++++++ ObjectPoolContainerRestAPI.cs | 97 ++++++++++++++++++++++++++++++++ ObjectRequest.cs | 30 ++++++++++ Properties/AssemblyInfo.cs | 26 +++++++++ TypeReflection.cs | 17 ++++++ ln.json.http.csproj | 60 ++++++++++++++++++++ ln.json.http.csproj.user | 7 +++ 13 files changed, 497 insertions(+) create mode 100644 .gitignore create mode 100644 HTTPRequestExtensions.cs create mode 100644 HttpObjectContainer.cs create mode 100644 HttpObjectMapper.cs create mode 100644 IObjectHandler.cs create mode 100644 MappingContainer.cs create mode 100644 ObjectHandler.cs create mode 100644 ObjectPoolContainerRestAPI.cs create mode 100644 ObjectRequest.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 TypeReflection.cs create mode 100644 ln.json.http.csproj create mode 100644 ln.json.http.csproj.user diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..790f01f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +obj +bin +ln.types +ln.logging \ No newline at end of file diff --git a/HTTPRequestExtensions.cs b/HTTPRequestExtensions.cs new file mode 100644 index 0000000..2ae7c1a --- /dev/null +++ b/HTTPRequestExtensions.cs @@ -0,0 +1,21 @@ +using System; +using ln.http; +using ln.json.mapping; +namespace ln.json.http +{ + public static class HTTPRequestExtensions + { + public static HttpResponse SendJSON(this HttpRequest request, object value) + { + HttpResponse response = new HttpResponse(request); + response.SetHeader("Content-Type", "application/json"); + response.ContentWriter.Write( + (value is JSONValue jvalue) ? jvalue.ToString() : JSONMapper.DefaultMapper.ToJson(value).ToString() + ); + response.ContentWriter.Flush(); + return response; + } + + public static JSONValue GetJSON(this HttpRequest httpRequest) => JSONParser.Parse(httpRequest.ContentReader.ReadToEnd()); + } +} diff --git a/HttpObjectContainer.cs b/HttpObjectContainer.cs new file mode 100644 index 0000000..641b686 --- /dev/null +++ b/HttpObjectContainer.cs @@ -0,0 +1,43 @@ +using System; +using ln.http.router; +using ln.http.exceptions; +using ln.http; +using ln.json.mapping; +using ln.types.odb.ng; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +namespace ln.json.http +{ + public abstract class HttpObjectContainer : SimpleRouter + { + public HttpObjectContainer() + { + } + + public abstract object GetNativeIdentity(string identityText); + public abstract object GetObjectIdentity(object o); + + public abstract object CreateObject(); + public abstract void DeleteObject(object o); + + public abstract IEnumerable GetObjects(); + public virtual object GetObject(object identity) + { + foreach (object o in GetObjects()) + { + if (Object.Equals(identity, GetObjectIdentity(o))) + return o; + } + throw new KeyNotFoundException(); + } + + + + HttpResponse Request(HttpRequest request) + { + + throw new NotImplementedException(); + } + } +} diff --git a/HttpObjectMapper.cs b/HttpObjectMapper.cs new file mode 100644 index 0000000..b2cd734 --- /dev/null +++ b/HttpObjectMapper.cs @@ -0,0 +1,22 @@ +using System; +using ln.http; +using System.Collections; +using System.Collections.Generic; +namespace ln.json.http +{ + public class HttpObjectMapper + { + public Type NativeType { get; } + + public HttpObjectMapper(Type nativeType) + { + NativeType = nativeType; + } + + public HttpResponse Request(ObjectRequest objectRequest) + { + throw new NotImplementedException(); + } + + } +} diff --git a/IObjectHandler.cs b/IObjectHandler.cs new file mode 100644 index 0000000..bbc4a69 --- /dev/null +++ b/IObjectHandler.cs @@ -0,0 +1,11 @@ +using System; +using ln.http; +using System.Collections; +using System.Collections.Generic; +namespace ln.json.http +{ + public interface IObjectHandler + { + HttpResponse Dispatch(HttpRequest httpRequest, object owner, Queue pathQueue); + } +} diff --git a/MappingContainer.cs b/MappingContainer.cs new file mode 100644 index 0000000..aac6f33 --- /dev/null +++ b/MappingContainer.cs @@ -0,0 +1,103 @@ +// /** +// * File: MappingContainer.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 ln.http; +using System.Collections.Generic; +using ln.http.router; +using ln.http.exceptions; +using ln.json.mapping; +using ln.types.odb.ng; +namespace ln.json.http +{ + public class MappingContainer: SimpleRouter + { + Mapper Mapper { get; } + Dictionary typeCache = new Dictionary(); + + public MappingContainer(Mapper mapper) + { + Mapper = mapper; + + AddSimpleRoute("/:type/:identity", Request); + AddSimpleRoute("/:type", Request); + } + public void AddSupportedType() => AddSupportedType(typeof(T)); + public void AddSupportedType(Type type) + { + typeCache.Add(type.Name, type); + } + + Type FindType(HttpRequest request) + { + if (request.ContainsParameter("type")) + { + return typeCache[request.GetParameter("type")]; + } + throw new KeyNotFoundException(); + } + + public HttpResponse RedirectTo(HttpRequest request, object item) + { + if (!Mapper.IdentityCache.TryGetIdentity(item, out Guid identity)) + throw new HttpException(500, "Internal Failure"); + + return request.Redirect("{0}", /*request.GetParameter("type"),*/ identity ); + } + + public HttpResponse Request(HttpRequest request) + { + Type requestedType = FindType(request); + + if (request.ContainsParameter("identity")) + { + if (request.Method.Equals("GET")) + { + object o = Mapper.Load(requestedType, Guid.Parse(request.GetParameter("identity"))); + if (o == null) + throw new HttpException(404, "Not Found"); + + return request.SendJSON(o); + } + else if (request.Method.Equals("PUT")) + { + object o = Mapper.Load(requestedType, Guid.Parse(request.GetParameter("identity"))); + if (o == null) + throw new HttpException(404, "Not Found"); + JSONMapper.DefaultMapper.Apply(request.ContentReader.ReadToEnd(), o); + Mapper.Save(requestedType, o); + + return RedirectTo(request, o); + } + else + throw new MethodNotAllowedException(); + } + else if (request.Method.Equals("GET")) + { + JSONObject jo = new JSONObject(); + foreach (Guid identity in Mapper.GetDocumentIDs(requestedType)) + { + jo[identity.ToString()] = JSONMapper.DefaultMapper.ToJson(Mapper.Load(requestedType, identity)); + } + return request.SendJSON(jo); + } + else if (request.Method.Equals("POST")) + { + if (!request.GetRequestHeader("content-type").Equals("application/json")) + throw new UnsupportedMediaTypeException(); + + object o = JSONMapper.DefaultMapper.FromJson(request.ContentReader.ReadToEnd(), requestedType); + Mapper.Save(requestedType, o); + + return RedirectTo(request, o); + } + throw new BadRequestException(); + } + } +} diff --git a/ObjectHandler.cs b/ObjectHandler.cs new file mode 100644 index 0000000..b7cc1c5 --- /dev/null +++ b/ObjectHandler.cs @@ -0,0 +1,56 @@ +// /** +// * File: ObjectHandler.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.Collections.Generic; +using ln.http; +using ln.types.reflection; +using ln.json.mapping; + +namespace ln.json.http +{ + public class ObjectHandler + { + public ObjectHandler() + { + } + + public HttpResponse DoObject(HttpRequest httpRequest, object o, Queue pathQueue) + { + if (pathQueue.Count > 1) + { + string next = pathQueue.Dequeue(); + TypeDescriptor typeDescriptor = TypeDescriptor.GetDescriptor(o.GetType()); + + if (typeDescriptor.ContainsAttribute(next)) + { + + } + } + else if (pathQueue.Count == 0) + { + switch (httpRequest.Method) + { + case "GET": + return httpRequest.SendJSON(JSONMapper.DefaultMapper.ToJson(o)); + case "PUT": + + break; + default: + throw new NotImplementedException(); + } + } + else + { + + } + throw new NotImplementedException(); + } + } +} diff --git a/ObjectPoolContainerRestAPI.cs b/ObjectPoolContainerRestAPI.cs new file mode 100644 index 0000000..19cc226 --- /dev/null +++ b/ObjectPoolContainerRestAPI.cs @@ -0,0 +1,97 @@ +using System; +using ln.http.router; +using ln.http; +using System.Collections.Generic; +using System.Reflection; +using ln.types; +using ln.json.mapping; +using ln.http.exceptions; +using System.Linq; +using ln.logging; +using ln.types.reflection; +using ln.json.reflection; +namespace ln.json.http +{ + public class ObjectPoolContainerRestAPI : SimpleRouter + { + public ObjectPoolContainer ObjectPoolContainer { get; } + public ObjectPoolContainerSerializer ObjectPoolContainerSerializer { get; } + + public ObjectPoolContainerRestAPI():this(new ObjectPoolContainer()) { } + public ObjectPoolContainerRestAPI(ObjectPoolContainer objectPoolContainer) + { + AddSimpleRoute("/:type", RequestType); + AddSimpleRoute("/:type/:identity", RequestInstance); + AddSimpleRoute("/:type/:identity/*", RequestInstancePath); + + ObjectPoolContainer = objectPoolContainer; + ObjectPoolContainerSerializer = new ObjectPoolContainerSerializer(objectPoolContainer); + } + + HttpResponse RequestType(HttpRequest httpRequest) + { + ObjectPool objectPool = ObjectPoolContainer[httpRequest.GetParameter("type")]; + + switch (httpRequest.Method) + { + case "GET": + JSONArray instanceList = new JSONArray(); + + foreach (object instance in objectPool.Instances) + { + instanceList.Add(ObjectPoolContainerSerializer.SerializeObject(objectPool, instance)); + } + + return httpRequest.SendJSON(instanceList); + case "POST": + object o = null; + try + { + o = ObjectPoolContainerSerializer.UnserializeObject(objectPool, httpRequest.GetJSON() as JSONObject); + objectPool.Add(o); + + return httpRequest.Redirect(objectPool.GetIdentity(o).ToString()); + } + catch (Exception e) + { + Logging.Log(e); + (o as IDisposable)?.Dispose(); + throw new HttpException(500, String.Format("Internal Error {0}", e.ToString())); + } + } + throw new NotImplementedException(); + } + HttpResponse RequestInstance(HttpRoutingContext routingContext, HttpRequest httpRequest) + { + ObjectPool objectPool = ObjectPoolContainer[httpRequest.GetParameter("type")]; + object o = objectPool[Cast.To(httpRequest.GetParameter("identity"), objectPool.IdentityType)]; + + switch (httpRequest.Method) + { + case "DELETE": + objectPool.Remove(objectPool.GetIdentity(o)); + HttpResponse httpResponse = new HttpResponse(httpRequest); + httpResponse.StatusCode = 204; + return httpResponse; + case "PUT": + object identity = objectPool.GetIdentity(o); + ObjectPoolContainerSerializer.UpdateObject(objectPool, o, httpRequest.GetJSON() as JSONObject); + if (!objectPool.GetIdentity(o).Equals(identity)) + { + objectPool.Remove(identity); + objectPool.Add(o); + } + return httpRequest.Redirect(objectPool.GetIdentity(o).ToString()); + case "GET": + return httpRequest.SendJSON(ObjectPoolContainerSerializer.SerializeObject(objectPool, o)); + } + throw new BadRequestException(); + } + HttpResponse RequestInstancePath(HttpRoutingContext routingContext, HttpRequest httpRequest) + { + // ToDo: Implement Sub-Instance Level access... + throw new NotImplementedException(); + } + + } +} diff --git a/ObjectRequest.cs b/ObjectRequest.cs new file mode 100644 index 0000000..6731d0c --- /dev/null +++ b/ObjectRequest.cs @@ -0,0 +1,30 @@ +using System; +using ln.http; +using System.Collections; +namespace ln.json.http +{ + public class ObjectRequest + { + public ObjectRequest ParentRequest { get; } + public HttpRequest HttpRequest { get; } + + public string[] RequestPath { get; } + public object Value { get; } + + public ObjectRequest(HttpRequest httpRequest,string requestPath) + { + HttpRequest = httpRequest; + RequestPath = requestPath.Split(new char[] { '/' }); + } + ObjectRequest(ObjectRequest parentRequest,HttpRequest httpRequest,string[] requestPath,object lastValue) + { + ParentRequest = parentRequest; + HttpRequest = httpRequest; + RequestPath = requestPath; + Value = lastValue; + } + + public string[] RequestedPath => throw new NotImplementedException(); + + } +} diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..86872d4 --- /dev/null +++ b/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("ln.json.http")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/TypeReflection.cs b/TypeReflection.cs new file mode 100644 index 0000000..7dd959c --- /dev/null +++ b/TypeReflection.cs @@ -0,0 +1,17 @@ +using System; +using ln.json.mapping; +namespace ln.json.http +{ + public class TypeReflection + { + public Type NativeType { get; } + + public TypeReflection() + { + } + + public JSONValue ToJSON(object value) => JSONMapper.DefaultMapper.ToJson(value); + + + } +} diff --git a/ln.json.http.csproj b/ln.json.http.csproj new file mode 100644 index 0000000..838fb6e --- /dev/null +++ b/ln.json.http.csproj @@ -0,0 +1,60 @@ + + + + Debug + AnyCPU + {9D06CBC0-9AED-48A8-8080-1514109E5AB3} + Library + ln.json.http + ln.json.http + v4.7 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + + + + + + + {CEEEEB41-3059-46A2-A871-2ADE22C013D9} + ln.http + + + {D9342117-3249-4D8B-87C9-51A50676B158} + ln.json + + + {8D9AB9A5-E513-4BA7-A450-534F6456BF28} + ln.types + + + {D471A566-9FB6-41B2-A777-3C32874ECD0E} + ln.logging + + + + \ No newline at end of file diff --git a/ln.json.http.csproj.user b/ln.json.http.csproj.user new file mode 100644 index 0000000..7306da1 --- /dev/null +++ b/ln.json.http.csproj.user @@ -0,0 +1,7 @@ + + + + Project + true + + \ No newline at end of file