新增适配xxl-jobv2.2+以上版本

pull/22/head
Xuanye Wong 6 years ago
parent db29347e37
commit e2d82ae952
  1. 51
      DotXxlJob.sln
  2. 54
      README.md
  3. 7
      build/releasenotes.props
  4. 3
      build/version.props
  5. 27
      samples/ASPNetCoreExecutor/Extensions/XxlJobExecutorMiddleware.cs
  6. 2
      samples/ASPNetCoreExecutor/Properties/launchSettings.json
  7. 8
      samples/ASPNetCoreExecutor/appsettings.json
  8. 23
      samples/HessianReader/HessianReader.csproj
  9. 73
      samples/HessianReader/NewFile1.txt
  10. 74
      samples/HessianReader/NewFile2.txt
  11. 158
      samples/HessianReader/Program.cs
  12. BIN
      samples/HessianReader/kill.dat
  13. BIN
      samples/HessianReader/log.dat
  14. BIN
      samples/HessianReader/request.dat
  15. BIN
      samples/HessianReader/run.dat
  16. 18
      scripts/nuget-hessian.sh
  17. 4
      scripts/nuget.sh
  18. 2
      scripts/package.sh
  19. 147
      src/DotXxlJob.Core/AdminClient.cs
  20. 12
      src/DotXxlJob.Core/DotXxlJob.Core.csproj
  21. 2
      src/DotXxlJob.Core/ExecutorRegistry.cs
  22. 9
      src/DotXxlJob.Core/Extensions/DateTimeExtension.cs
  23. 2
      src/DotXxlJob.Core/Extensions/ServiceCollectionExtensions.cs
  24. 132
      src/DotXxlJob.Core/Internal/HessianObjectConvert.cs
  25. 79
      src/DotXxlJob.Core/Internal/HessianSerializer.cs
  26. 2
      src/DotXxlJob.Core/Logger/JobLogger.cs
  27. 2
      src/DotXxlJob.Core/Model/AddressEntity.cs
  28. 15
      src/DotXxlJob.Core/Model/IdleBeatRequest.cs
  29. 16
      src/DotXxlJob.Core/Model/KillRequest.cs
  30. 21
      src/DotXxlJob.Core/Model/LogRequest.cs
  31. 6
      src/DotXxlJob.Core/Model/RegistryParam.cs
  32. 16
      src/DotXxlJob.Core/Model/TriggerParam.cs
  33. 166
      src/DotXxlJob.Core/XxlRestfulServiceHandler.cs
  34. 217
      src/DotXxlJob.Core/XxlRpcServiceHandler.cs
  35. 59
      src/Hessian/ClassDef.cs
  36. 11
      src/Hessian/ClassElement.cs
  37. 91
      src/Hessian/Collections/ForwardingDictionary.cs
  38. 32
      src/Hessian/Collections/IRefMap.cs
  39. 59
      src/Hessian/Collections/ITwoWayDictionary.cs
  40. 34
      src/Hessian/Collections/ListRefMap.cs
  41. 123
      src/Hessian/Collections/TwoWayDictionary.cs
  42. 34
      src/Hessian/Collections/TwoWayDictionaryRefMap.cs
  43. 114
      src/Hessian/Conditions.cs
  44. 1015
      src/Hessian/Deserializer.cs
  45. 46
      src/Hessian/DictionaryTypeResolver.cs
  46. 24
      src/Hessian/Hessian.csproj
  47. 24
      src/Hessian/HessianException.cs
  48. 66
      src/Hessian/HessianObject.cs
  49. 27
      src/Hessian/HessianSerializationContext.cs
  50. 15
      src/Hessian/InvalidRefException.cs
  51. 66
      src/Hessian/ListTypeResolver.cs
  52. 39
      src/Hessian/Marker.cs
  53. 142
      src/Hessian/PeekStream.cs
  54. 25
      src/Hessian/Platform/BigEndianBitConverter.cs
  55. 215
      src/Hessian/Platform/EndianBitConverter.cs
  56. 25
      src/Hessian/Platform/LittleEndianBitConverter.cs
  57. 31
      src/Hessian/PropertyElement.cs
  58. 523
      src/Hessian/Serializer.cs
  59. 39
      src/Hessian/StringBuilderExtensions.cs
  60. 18
      src/Hessian/UnexpectedTagException.cs
  61. 163
      src/Hessian/ValueReader.cs
  62. 19
      tests/Hessian.Tests/Hessian.Tests.csproj
  63. 13
      tests/Hessian.Tests/UnitTest1.cs

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.30104.148
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{97756BA5-1E7C-4536-A49E-AE2190C0E6A5}"
EndProject
@ -13,13 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E959
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ASPNetCoreExecutor", "samples\ASPNetCoreExecutor\ASPNetCoreExecutor.csproj", "{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HessianReader", "samples\HessianReader\HessianReader.csproj", "{F822B528-95FD-40B4-9EE0-3AE8878075AC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hessian", "src\Hessian\Hessian.csproj", "{BD9B8108-6528-430F-AD28-6F8434A29F55}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hessian.Tests", "tests\Hessian.Tests\Hessian.Tests.csproj", "{A51FACF0-C90F-43D1-898D-CD171977C1A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotXxlJob.Core.Tests", "tests\DotXxlJob.Core.Tests\DotXxlJob.Core.Tests.csproj", "{81C60471-7C1C-48CE-98C0-F252C267AC9F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotXxlJob.Core.Tests", "tests\DotXxlJob.Core.Tests\DotXxlJob.Core.Tests.csproj", "{81C60471-7C1C-48CE-98C0-F252C267AC9F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -55,42 +49,6 @@ Global
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x64.Build.0 = Release|Any CPU
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x86.ActiveCfg = Release|Any CPU
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x86.Build.0 = Release|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x64.ActiveCfg = Debug|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x64.Build.0 = Debug|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x86.ActiveCfg = Debug|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x86.Build.0 = Debug|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|Any CPU.Build.0 = Release|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x64.ActiveCfg = Release|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x64.Build.0 = Release|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x86.ActiveCfg = Release|Any CPU
{F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x86.Build.0 = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x64.ActiveCfg = Debug|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x64.Build.0 = Debug|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x86.ActiveCfg = Debug|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x86.Build.0 = Debug|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|Any CPU.Build.0 = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x64.ActiveCfg = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x64.Build.0 = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x86.ActiveCfg = Release|Any CPU
{BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x86.Build.0 = Release|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Debug|x64.ActiveCfg = Debug|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Debug|x64.Build.0 = Debug|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Debug|x86.ActiveCfg = Debug|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Debug|x86.Build.0 = Debug|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Release|Any CPU.Build.0 = Release|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Release|x64.ActiveCfg = Release|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Release|x64.Build.0 = Release|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Release|x86.ActiveCfg = Release|Any CPU
{A51FACF0-C90F-43D1-898D-CD171977C1A1}.Release|x86.Build.0 = Release|Any CPU
{81C60471-7C1C-48CE-98C0-F252C267AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81C60471-7C1C-48CE-98C0-F252C267AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81C60471-7C1C-48CE-98C0-F252C267AC9F}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -110,9 +68,6 @@ Global
GlobalSection(NestedProjects) = preSolution
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
{F822B528-95FD-40B4-9EE0-3AE8878075AC} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
{BD9B8108-6528-430F-AD28-6F8434A29F55} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{A51FACF0-C90F-43D1-898D-CD171977C1A1} = {352EC932-F112-4A2F-9DC3-F0761C85E068}
{81C60471-7C1C-48CE-98C0-F252C267AC9F} = {352EC932-F112-4A2F-9DC3-F0761C85E068}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution

@ -1,5 +1,6 @@
# DotXxlJob
xxl-job的dotnet core 执行器实现,支持XXL-JOB 2.0+
xxl-job的dotnet core 最新执行器实现,支持XXL-JOB 2.2+
> 注意XXL-JOB 2.0-2.2版本请使用 1.0.8的执行器实现
## 1 XXL-JOB概述
[XXL-JOB][1]是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。以下是它的架构图
@ -25,34 +26,37 @@ xxl-job的dotnet core 执行器实现,支持XXL-JOB 2.0+
1. 声明一个AspNet的Middleware中间件,并扩展ApplicationBuilder,本质是拦截Post请求,解析Body中的流信息
```
public class XxlJobExecutorMiddleware
{
private readonly IServiceProvider _provider;
private readonly RequestDelegate _next;
private readonly XxlRpcServiceHandler _rpcService;
public XxlJobExecutorMiddleware(IServiceProvider provider, RequestDelegate next)
public class XxlJobExecutorMiddleware
{
this._provider = provider;
this._next = next;
this._rpcService = _provider.GetRequiredService<XxlRpcServiceHandler>();
}
private readonly IServiceProvider _provider;
private readonly RequestDelegate _next;
public async Task Invoke(HttpContext context)
{
private readonly XxlRestfulServiceHandler _rpcService;
public XxlJobExecutorMiddleware(IServiceProvider provider, RequestDelegate next)
{
this._provider = provider;
this._next = next;
this._rpcService = _provider.GetRequiredService<XxlRestfulServiceHandler>();
}
if ("POST".Equals(context.Request.Method, StringComparison.OrdinalIgnoreCase) &&
"application/octet-stream".Equals(context.Request.ContentType, StringComparison.OrdinalIgnoreCase))
public async Task Invoke(HttpContext context)
{
var rsp = await _rpcService.HandlerAsync(context.Request.Body);
context.Response.StatusCode = (int) HttpStatusCode.OK;
context.Response.ContentType = "text/plain;utf-8";
await context.Response.Body.WriteAsync(rsp,0,rsp.Length);
return;
string contentType = context.Request.ContentType;
if ("POST".Equals(context.Request.Method, StringComparison.OrdinalIgnoreCase)
&& !string.IsNullOrEmpty(contentType)
&& contentType.ToLower().StartsWith("application/json"))
{
await _rpcService.HandlerAsync(context.Request,context.Response);
return;
}
await _next.Invoke(context);
}
await _next.Invoke(context);
}
}
```
扩展ApplicationBuilderExtensions,可根据实际情况绑定在特殊的Url Path上
@ -151,12 +155,10 @@ public class DemoJobHandler:AbstractJobHandler
public int LogRetentionDays { get; set; } = 30;
}
```
## 在其他Http服务中使用
只需要实现Http请求的拦截,并判断post请求中content-Type="application/octet-stream",并使用XxlRpcServiceHandler来处理流 即可。
## 其他说明
XXL-JOB内置的RPC是使用Hessian协议,这个有点坑。很多都是java特有的属性和标识,比如类名什么的。在本项目中,并没有实现完整的Hessian2协议,只实现了使用到的类型,当然扩展起来也非常方便。如果有人要单独使用Hessian 这个类库的话,要特别注意这个问题。
注意XXL-JOB 2.0-2.2版本请使用 1.0.8的执行器实现
有任何问题,可Issue反馈 ,最后感谢 xxl-job

@ -1,10 +1,7 @@
<Project>
<PropertyGroup>
<DotXxlJobPackageNotes>
1. 修复回调一次过多的问题
</DotXxlJobPackageNotes>
<HessianPackageNotes>
1. 实现基本的Hessian协议
</HessianPackageNotes>
1. 修改接口方式为Restful方式,适配xxl-jobv2.2以上版本
</DotXxlJobPackageNotes>
</PropertyGroup>
</Project>

@ -1,6 +1,5 @@
<Project>
<PropertyGroup>
<DotXxlJobPackageVersion>1.0.8</DotXxlJobPackageVersion>
<HessianPackageVersion>1.0.1</HessianPackageVersion>
<DotXxlJobPackageVersion>2.0.0</DotXxlJobPackageVersion>
</PropertyGroup>
</Project>

@ -13,35 +13,26 @@ namespace ASPNetCoreExecutor
private readonly IServiceProvider _provider;
private readonly RequestDelegate _next;
private readonly XxlRpcServiceHandler _rpcService;
private readonly XxlRestfulServiceHandler _rpcService;
public XxlJobExecutorMiddleware(IServiceProvider provider, RequestDelegate next)
{
this._provider = provider;
this._next = next;
this._rpcService = _provider.GetRequiredService<XxlRpcServiceHandler>();
this._rpcService = _provider.GetRequiredService<XxlRestfulServiceHandler>();
}
public async Task Invoke(HttpContext context)
{
string contentType = context.Request.ContentType;
if ("POST".Equals(context.Request.Method, StringComparison.OrdinalIgnoreCase) &&
"application/octet-stream".Equals(context.Request.ContentType, StringComparison.OrdinalIgnoreCase))
if ("POST".Equals(context.Request.Method, StringComparison.OrdinalIgnoreCase)
&& !string.IsNullOrEmpty(contentType)
&& contentType.ToLower().StartsWith("application/json"))
{
/*
using (Stream file = File.Create("./"+DateTime.Now.ToUnixTimeSeconds()+".data"))
{
context.Request.Body.CopyTo(file);
}
return;
*/
var rsp = await _rpcService.HandlerAsync(context.Request.Body);
context.Response.StatusCode = (int) HttpStatusCode.OK;
context.Response.ContentType = "text/plain;utf-8";
await context.Response.Body.WriteAsync(rsp,0,rsp.Length);
await _rpcService.HandlerAsync(context.Request,context.Response);
return;
}

@ -21,7 +21,7 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:60088/"
"applicationUrl": "http://localhost:5000/"
}
}
}

@ -1,16 +1,16 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning"
"Default": "Information"
}
},
"xxlJob": {
"adminAddresses":"http://127.0.0.1:8080",
"adminAddresses": "http://127.0.0.1:8080/xxl-job-admin",
"appName": "xxl-job-executor-dotnet",
"specialBindAddress": "127.0.0.1",
"port": 5000,
"autoRegistry":false,
"accessToken": "",
"autoRegistry": true,
"accessToken": "",
"logRetentionDays": 30
}

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\DotXxlJob.Core\DotXxlJob.Core.csproj" />
<ProjectReference Include="..\..\src\Hessian\Hessian.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="run.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -1,73 +0,0 @@
------------ 0x43----------------
ReadClassDefinition
Hessian.ClassDef={"Name":"com.xxl.rpc.remoting.net.params.XxlRpcRequest","Fields":["requestId","createMillisTime","accessToken","className","methodName","version","parameterTypes","parameters"]}
------------------------------------------------------------
------------ 0x60----------------
ReadObjectCompact XxlRpcRequest
------------ 0x30----------------
ReadMediumString requestId
------------ 0x4c----------------
ReadLongFull createMillisTime
------------ 0x00----------------
ReadShortString accessToken
------------ 0x1d----------------
ReadShortString className
------------ 0x08----------------
ReadShortString methodName
------------ 0x4e----------------
ReadNull version
------------ 0x71----------------
ReadCompactFixList parameterTypes
------------ 0x43----------------
ReadClassDefinition java.lang.Class
------------ 0x61----------------
ReadObjectCompact java.lang.Class
------------ 0x0e----------------
ReadShortString name
Hessian.HessianObject=[{"Item1":"requestId","Item2":"e24123be4a76417ca6f41f227532b235"},{"Item1":"createMillisTime","Item2":1547819469003},{"Item1":"accessToken","Item2":""},{"Item1":"className","Item2":"com.xxl.job.core.biz.AdminBiz"},{"It
em1":"methodName","Item2":"callback"},{"Item1":"version","Item2":null},{"Item1":"parameterTypes","Item2":[{"Name":"java.lang.Class","Fields":["name"]}]},{"Item1":"parameters","Item2":[{"Item1":"name","Item2":"java.util.List"}]}]
------------------------------------------------------------
------------ 0x71----------------
ReadCompactFixList parameters
------------ 0x72----------------
ReadCompactFixList List
------------ 0x43----------------
ReadClassDefinition HandleCallbackParam
------------ 0x62----------------
ReadObjectCompact HandleCallbackParam
------------ 0x9b----------------
ReadIntegerSingleByte logId
------------ 0x4c----------------
ReadLongFull logDateTim
------------ 0x43----------------
ReadClassDefinition executeResult
System.Collections.Generic.List`1[System.Object]=[[{"Name":"com.xxl.job.core.biz.model.HandleCallbackParam","Fields":["logId","logDateTim","executeResult"]},[{"Item1":"logId","Item2":11},{"Item1":"logDateTim","Item2":1547819469000},{"Item1"
:"executeResult","Item2":{"Name":"com.xxl.job.core.biz.model.ReturnT","Fields":["code","msg","content"]}}]]]
------------------------------------------------------------
------------ 0x63----------------
ReadObjectCompact executeResult
------------ 0xc8----------------
ReadIntegerTwoBytes code
------------ 0x03----------------
ReadShortString msg
------------ 0x07----------------
ReadShortString content
Hessian.HessianObject=[{"Item1":"code","Item2":200},{"Item1":"msg","Item2":"1bc"},{"Item1":"content","Item2":"acd3323"}]
------------------------------------------------------------
------------ 0x62----------------
ReadObjectCompact HandleCallbackParam
------------ 0xa6----------------
ReadIntegerSingleByte logId
------------ 0x4c----------------
ReadLongFull logDateTim
------------ 0x63----------------
ReadObjectCompact executeResult
------------ 0xc9----------------
ReadIntegerTwoBytes code
------------ 0x03----------------
ReadShortString msg
------------ 0x03----------------
ReadShortString content
Hessian.HessianObject=[{"Item1":"logId","Item2":22},{"Item1":"logDateTim","Item2":1547819469000},{"Item1":"executeResult","Item2":[{"Item1":"code","Item2":500},{"Item1":"msg","Item2":"cac"},{"Item1":"content","Item2":"aad"}]}]
------------------------------------------------------------
------------------------------------------------------------

@ -1,74 +0,0 @@
---------------------------------------------------------------
------------ 0x43----------------
ReadClassDefinition
Hessian.ClassDef={"Name":"com.xxl.rpc.remoting.net.params.XxlRpcRequest","Fields":["requestId","createMillisTime","accessToken","className","methodName","version","parameterTypes","parameters"]}
------------------------------------------------------------
------------ 0x60----------------
ReadObjectCompact
------------ 0x30----------------
ReadMediumString
------------ 0x4c----------------
ReadLongFull
------------ 0x00----------------
ReadShortString
------------ 0x1d----------------
ReadShortString
------------ 0x08----------------
ReadShortString
------------ 0x4e----------------
ReadNull
------------ 0x71----------------
ReadCompactFixList
------------ 0x43----------------
ReadClassDefinition
------------ 0x61----------------
ReadObjectCompact
------------ 0x0e----------------
ReadShortString
Hessian.HessianObject=[{"Item1":"requestId","Item2":"e24123be4a76417ca6f41f227532b235"},{"Item1":"createMillisTime","Item2":1547819469003},{"Item1":"accessToken","Item2":""},{"Item1":"className","Item2":"com.xxl.job.core.biz.AdminBiz"},{"I
tem1":"methodName","Item2":"callback"},{"Item1":"version","Item2":null},{"Item1":"parameterTypes","Item2":[{"Name":"java.lang.Class","Fields":["name"]}]},{"Item1":"parameters","Item2":[{"Item1":"name","Item2":"java.util.List"}]}]
------------------------------------------------------------
------------ 0x71----------------
ReadCompactFixList
------------ 0x72----------------
ReadCompactFixList
------------ 0x43----------------
ReadClassDefinition
------------ 0x62----------------
ReadObjectCompact
------------ 0x9b----------------
ReadIntegerSingleByte
------------ 0x4c----------------
ReadLongFull
------------ 0x43----------------
ReadClassDefinition
System.Collections.Generic.List`1[System.Object]=[[{"Name":"com.xxl.job.core.biz.model.HandleCallbackParam","Fields":["logId","logDateTim","executeResult"]},[{"Item1":"logId","Item2":11},{"Item1":"logDateTim","Item2":1547819469000},{"Item1
":"executeResult","Item2":{"Name":"com.xxl.job.core.biz.model.ReturnT","Fields":["code","msg","content"]}}]]]
------------------------------------------------------------
------------ 0x63----------------
ReadObjectCompact
------------ 0xc8----------------
ReadIntegerTwoBytes
------------ 0x03----------------
ReadShortString
------------ 0x07----------------
ReadShortString
Hessian.HessianObject=[{"Item1":"code","Item2":200},{"Item1":"msg","Item2":"1bc"},{"Item1":"content","Item2":"acd3323"}]
------------------------------------------------------------
------------ 0x62----------------
ReadObjectCompact
------------ 0xa6----------------
ReadIntegerSingleByte
------------ 0x4c----------------
ReadLongFull
------------ 0x63----------------
ReadObjectCompact
------------ 0xc9----------------
ReadIntegerTwoBytes
------------ 0x03----------------
ReadShortString
------------ 0x03----------------
ReadShortString
Hessian.HessianObject=[{"Item1":"logId","Item2":22},{"Item1":"logDateTim","Item2":1547819469000},{"Item1":"executeResult","Item2":[{"Item1":"code","Item2":500},{"Item1":"msg","Item2":"aad"},{"Item1":"content","Item2":"cac"}]}]
------------------------------------------------------------
------------------------------------------------------------

@ -1,158 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using DotXxlJob.Core;
using DotXxlJob.Core.Model;
using Hessian;
using Newtonsoft.Json;
namespace HessianReader
{
class Program
{
static void Main(string[] args)
{
/* */
byte[] myBinary = File.ReadAllBytes("run.dat");
foreach (var i in myBinary)
{
Console.Write("0x");
Console.Write(i.ToString("x2"));
Console.Write(",");
}
Console.WriteLine(Environment.NewLine);
Console.WriteLine("---------------------------------------------------------------");
/*
byte[] myBinary;
var callbackParamList = new List<HandleCallbackParam> {
new HandleCallbackParam {
LogId = 11,
LogDateTime = 1547819469000L,
ExecuteResult =new ReturnT { Code = 200,Content ="acd3323",Msg ="1bc" }
},
new HandleCallbackParam {
LogId = 22,
LogDateTime = 1547819469000L,
ExecuteResult =new ReturnT { Code = 500,Content ="cac",Msg ="aad" }
}
};
var request = new RpcRequest {
RequestId ="e24123be4a76417ca6f41f227532b235",
CreateMillisTime = 1547819469003L,
AccessToken = "",
ClassName = "com.xxl.job.core.biz.AdminBiz",
MethodName = "callback",
ParameterTypes = new List<object> {new JavaClass {Name = "java.util.List"}},
Parameters = new List<object> {callbackParamList}
};
using (var stream = new MemoryStream())
{
HessianSerializer.SerializeRequest(stream,request);
myBinary = stream.ToArray();
}
*/
using (var stream1 = new MemoryStream(myBinary))
{
var s1 = HessianSerializer.DeserializeRequest(stream1);
Console.WriteLine("{0}={1}",s1.GetType(),JsonConvert.SerializeObject(s1));
/*
var s = new Deserializer(stream1);
while ( s.CanRead())
{
var o = s.ReadValue();
Console.WriteLine("{0}={1}",o.GetType(),JsonConvert.SerializeObject(o));
Console.WriteLine("------------------------------------------------------------");
}
*/
}
Console.WriteLine("------------------------------------------------------------");
Console.ReadKey();
/**
*
* Console.WriteLine("---------------------------------------------------------------");
RpcRequest req = new RpcRequest {
RequestId = "71565f61-94e8-4dcf-9760-f2fb73a6886a",
CreateMillisTime = 1547621183585,
AccessToken = "",
ClassName = "com.xxl.job.core.biz.ExecutorBiz",
MethodName = "run",
ParameterTypes = new List<object> {new JavaClass{ Name = "com.xxl.job.core.biz.model.TriggerParam"}},
Version = null,
Parameters = new List<object>()
};
var p =new TriggerParam {
JobId=1,
ExecutorHandler="demoJobHandler",
ExecutorParams="111",
ExecutorBlockStrategy="SERIAL_EXECUTION",
ExecutorTimeout=0,
LogId=5,
LogDateTime=1547621183414L,
GlueType="BEAN",
GlueSource="",
GlueUpdateTime=1541254891000,
BroadcastIndex=0,
BroadcastTotal=1
};
req.Parameters.Add(p);
using (var stream2 = new MemoryStream())
{
var serializer = new Serializer(stream2);
serializer.WriteObject(req);
Console.WriteLine("-----------------------------序列化成功---{0}-------------------------------",stream2.Length);
stream2.Position = 0;
var s2 = HessianSerializer.DeserializeRequest(stream2);
Console.WriteLine(JsonConvert.SerializeObject(s2));
}
* [{"Item1":"requestId","Item2":"71565f61-94e8-4dcf-9760-f2fb73a6886a"},{"Item1":"createMillisTime","Item2":1432957289},{"Item1":"accessToken","Item2":""},{"Item1":"className","Item2":"com.xxl.job.core.biz.ExecutorBiz"},{"Item1":"methodName","Item2":"run"},{"Item1":"version","Item2":null},{"Item1":"parameterT
ypes","Item2":[{"Name":"java.lang.Class","Fields":["name"]}]},{"Item1":"parameters","Item2":[{"Item1":"name","Item2":"com.xxl.job.core.biz.model.TriggerParam"}]}]
System.Collections.Generic.List`1[System.Object]
[{"Name":"com.xxl.job.core.biz.model.TriggerParam","Fields":["jobId","executorHandler","executorParams","executorBlockStrategy","executorTimeout","logId","logDateTim","glueType","glueSource","glueUpdatetime","broadcastIndex","broadcastTotal"]}]
Hessian.HessianObject
[{"Item1":"jobId","Item2":1},{"Item1":"executorHandler","Item2":"demoJobHandler"},{"Item1":"executorParams","Item2":"111"},{"Item1":"executorBlockStrategy","Item2":"SERIAL_EXECUTION"},{"Item1":"executorTimeout","Item2":0},{"Item1":"logId","Item2":5},{"Item1":"logDateTim","Item2":1432956926},{"Item1":"glueTy
pe","Item2":"BEAN"},{"Item1":"glueSource","Item2":""},{"Item1":"glueUpdatetime","Item2":-638368258},{"Item1":"broadcastIndex","Item2":0},{"Item1":"broadcastTotal","Item2":1}]
* requestId='71565f61-94e8-4dcf-9760-f2fb73a6886a',
* createMillisTime=1547621183585,
* accessToken='',
* className='com.xxl.job.core.biz.ExecutorBiz',
* methodName='run',
* parameterTypes=[class com.xxl.job.core.biz.model.TriggerParam],
* parameters=[
* TriggerParam{
* jobId=1,
* executorHandler='demoJobHandler',
* executorParams='111',
* executorBlockStrategy='SERIAL_EXECUTION',
* executorTimeout=0,
* logId=5,
* logDateTim=1547621183414,
* glueType='BEAN',
* glueSource='',
* glueUpdatetime=1541254891000,
* broadcastIndex=0,
* broadcastTotal=1
* }
* ], version='null'
*
*/
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,18 +0,0 @@
set -ex
cd $(dirname $0)/../
artifactsFolder="./artifacts"
if [ -d $artifactsFolder ]; then
rm -R $artifactsFolder
fi
mkdir -p $artifactsFolder
dotnet build ./src/Hessian/Hessian.csproj -c Release
dotnet pack ./src/Hessian/Hessian.csproj -c Release -o ../../$artifactsFolder
dotnet nuget push ./$artifactsFolder/Hessian.*.nupkg -k $NUGET_KEY -s https://www.nuget.org

@ -13,6 +13,6 @@ mkdir -p $artifactsFolder
dotnet build ./src/DotXxlJob.Core/DotXxlJob.Core.csproj -c Release
dotnet pack ./src/DotXxlJob.Core/DotXxlJob.Core.csproj -c Release -o ../../$artifactsFolder
dotnet pack ./src/DotXxlJob.Core/DotXxlJob.Core.csproj -c Release -o $artifactsFolder
dotnet nuget push ./$artifactsFolder/DotXxlJob.Core.*.nupkg -k $NUGET_KEY -s https://www.nuget.org
dotnet nuget push $artifactsFolder/DotXxlJob.Core.*.nupkg -k $NUGET_KEY -s https://www.nuget.org

@ -14,4 +14,4 @@ dotnet restore ./DotXxlJob.sln
dotnet build ./DotXxlJob.sln -c Release
dotnet pack ./src/DotXxlJob.Core/DotXxlJob.Core.csproj -c Release -o ../../$artifactsFolder
dotnet pack ./src/DotXxlJob.Core/DotXxlJob.Core.csproj -c Release -o $artifactsFolder

@ -7,31 +7,28 @@ using System.Net.Http.Headers;
using System.Threading.Tasks;
using DotXxlJob.Core.Config;
using DotXxlJob.Core.Model;
using Hessian;
using Flurl;
using Flurl.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace DotXxlJob.Core
{
public class AdminClient
{
private static readonly string MAPPING = "/api";
private readonly XxlJobExecutorOptions _options;
private readonly IHttpClientFactory _clientFactory;
private readonly XxlJobExecutorOptions _options;
private readonly ILogger<AdminClient> _logger;
private List<AddressEntry> _addresses;
private int _currentIndex;
public AdminClient(IOptions<XxlJobExecutorOptions> optionsAccessor
, IHttpClientFactory clientFactory
private static readonly string MAPPING = "/api";
public AdminClient(IOptions<XxlJobExecutorOptions> optionsAccessor
, ILogger<AdminClient> logger)
{
Preconditions.CheckNotNull(optionsAccessor?.Value, "XxlJobExecutorOptions");
this._options = optionsAccessor?.Value;
this._clientFactory = clientFactory;
this._options = optionsAccessor?.Value;
this._logger = logger;
InitAddress();
}
@ -42,9 +39,8 @@ namespace DotXxlJob.Core
foreach (var item in this._options.AdminAddresses.Split(';'))
{
try
{
var uri = new Uri(item + MAPPING);
var entry = new AddressEntry { RequestUri = uri };
{
var entry = new AddressEntry { RequestUri = item+ MAPPING };
this._addresses.Add(entry);
}
catch (Exception ex)
@ -56,121 +52,58 @@ namespace DotXxlJob.Core
public Task<ReturnT> Callback(List<HandleCallbackParam> callbackParamList)
{
return InvokeRpcService("callback", new List<object> { new JavaClass { Name = Constants.JavaListFulName } }, callbackParamList);
return InvokeRpcService("callback", callbackParamList);
}
public Task<ReturnT> Registry(RegistryParam registryParam)
{
return InvokeRpcService("registry", new List<object> { new JavaClass { Name = "com.xxl.job.core.biz.model.RegistryParam" } }, registryParam, true);
return InvokeRpcService("registry", registryParam);
}
public Task<ReturnT> RegistryRemove(RegistryParam registryParam)
{
return InvokeRpcService("registryRemove", new List<object> { new JavaClass { Name = "com.xxl.job.core.biz.model.RegistryParam" } }, registryParam, true);
return InvokeRpcService("registryRemove", registryParam);
}
private async Task<ReturnT> InvokeRpcService(string methodName, List<object> parameterTypes,
object parameters, bool polling = false)
{
var request = new RpcRequest {
RequestId = Guid.NewGuid().ToString("N"),
CreateMillisTime = DateTime.Now.GetTotalMilliseconds(),
AccessToken = _options.AccessToken,
ClassName = "com.xxl.job.core.biz.AdminBiz",
MethodName = methodName,
ParameterTypes = parameterTypes,
Parameters = new List<object> { parameters }
};
byte[] postBuf;
using (var stream = new MemoryStream())
{
HessianSerializer.SerializeRequest(stream, request);
postBuf = stream.ToArray();
}
private async Task<ReturnT> InvokeRpcService(string methodName, object jsonObject)
{
var triedTimes = 0;
var retList = new List<ReturnT>();
ReturnT ret = null;
using (var client = this._clientFactory.CreateClient(Constants.DefaultHttpClientName))
while (triedTimes++ < this._addresses.Count)
{
while (triedTimes++ < this._addresses.Count)
{
var address = this._addresses[this._currentIndex];
this._currentIndex = (this._currentIndex + 1) % this._addresses.Count;
if (!address.CheckAccessible())
continue;
Stream resStream;
try
{
resStream = await DoPost(client, address, postBuf);
address.Reset();
}
catch (Exception ex)
{
this._logger.LogError(ex, "request admin error.{0}", ex.Message);
address.SetFail();
continue;
}
RpcResponse res = null;
try
{
/*
using (StreamReader reader = new StreamReader(resStream))
{
string content = await reader.ReadToEndAsync();
this._logger.LogWarning(content);
}
*/
res = HessianSerializer.DeserializeResponse(resStream);
}
catch (Exception ex)
{
this._logger.LogError(ex, "DeserializeResponse error:{errorMessage}", ex.Message);
}
var address = this._addresses[this._currentIndex];
this._currentIndex = (this._currentIndex + 1) % this._addresses.Count;
if (!address.CheckAccessible())
continue;
try
{
if (res == null)
{
retList.Add(ReturnT.Failed("response is null"));
}
else if (res.IsError)
{
retList.Add(ReturnT.Failed(res.ErrorMsg));
}
else if (res.Result is ReturnT ret)
{
retList.Add(ret);
}
else
{
retList.Add(ReturnT.Failed("response is null"));
}
var json = await address.RequestUri.AppendPathSegment(methodName)
.WithHeader("XXL-JOB-ACCESS-TOKEN", this._options.AccessToken)
.PostJsonAsync(jsonObject)
.ReceiveString();
if (!polling)
{
return retList[0];
}
//.ReceiveJson<ReturnT>();
ret = JsonConvert.DeserializeObject<ReturnT>(json);
address.Reset();
}
if (retList.Count > 0)
catch (Exception ex)
{
return retList.Last();
this._logger.LogError(ex, "request admin error.{0}", ex.Message);
address.SetFail();
continue;
}
}
if(ret == null)
{
ret = ReturnT.Failed("call admin fail");
}
throw new Exception("xxl-rpc server address not accessible.");
return ret;
}
private async Task<Stream> DoPost(HttpClient client, AddressEntry address, byte[] postBuf)
{
var content = new ByteArrayContent(postBuf);
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
var responseMessage = await client.PostAsync(address.RequestUri, content);
responseMessage.EnsureSuccessStatusCode();
return await responseMessage.Content.ReadAsStreamAsync();
}
}
}

@ -23,14 +23,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.1.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.1.0" />
<PackageReference Include="Flurl.Http" Version="2.4.2" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
<PackageReference Include="Utf8Json" Version="1.3.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Hessian\Hessian.csproj" />
</ItemGroup>
</Project>

@ -35,7 +35,7 @@ namespace DotXxlJob.Core
var registryParam = new RegistryParam {
RegistryGroup = "EXECUTOR",
RegistryKey = _options.AppName,
RegistryValue = $"{_options.SpecialBindAddress}:{_options.Port}"
RegistryValue = $"http://{_options.SpecialBindAddress}:{_options.Port}/"
};
_logger.LogInformation(">>>>>>>> start registry to admin <<<<<<<<");

@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Hessian
namespace DotXxlJob.Core.Extensions
{
/// <summary>
///
/// </summary>
public static class DateTimeExtension
{
private const long Era = 62135596800000L;
@ -17,7 +16,7 @@ namespace Hessian
/// <returns></returns>
public static long GetTotalMilliseconds(this DateTime dt)
{
return dt.ToUniversalTime().Ticks / 10000 - Era;
return dt.ToUniversalTime().Ticks / 10000 - Era;
}
/// <summary>

@ -51,7 +51,7 @@ namespace DotXxlJob.Core
services.AddHttpClient("DotXxlJobClient");
services.AddSingleton<JobDispatcher>();
services.AddSingleton<TaskExecutorFactory>();
services.AddSingleton<XxlRpcServiceHandler>();
services.AddSingleton<XxlRestfulServiceHandler>();
services.AddSingleton<CallbackTaskQueue>();
services.AddSingleton<AdminClient>();
services.AddSingleton<ITaskExecutor, TaskExecutors.BeanTaskExecutor>();

@ -1,132 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using DotXxlJob.Core.Model;
using Hessian;
namespace DotXxlJob.Core
{
public class HessianObjectHelper
{
private static readonly Dictionary<string,Dictionary<string,PropertyInfo>> TransferObjCache
= new Dictionary<string, Dictionary<string, PropertyInfo>>();
private static readonly Dictionary<string,Type> TransferTypeCache
= new Dictionary<string, Type>();
static HessianObjectHelper()
{
InitProperties(typeof(RpcRequest));
InitProperties(typeof(TriggerParam));
InitProperties(typeof(RpcResponse));
InitProperties(typeof(ReturnT));
InitProperties(typeof(HandleCallbackParam));
InitProperties(typeof(JavaClass));
InitProperties(typeof(RegistryParam));
InitProperties(typeof(LogResult));
}
private static void InitProperties(Type type)
{
var propertyInfos = new Dictionary<string, PropertyInfo>();
var typeInfo = type.GetTypeInfo();
var classAttr = type.GetCustomAttribute<DataContractAttribute>();
if (classAttr == null)
{
return;
}
foreach (var property in typeInfo.DeclaredProperties)
{
var attribute = property.GetCustomAttribute<DataMemberAttribute>();
if (null == attribute)
{
continue;
}
if (!property.CanRead || !property.CanWrite)
{
continue;
}
propertyInfos.Add(attribute.Name,property);
}
TransferTypeCache.Add(classAttr.Name,type);
TransferObjCache.Add(classAttr.Name,propertyInfos);
}
public static object GetRealObjectValue(Deserializer deserializer,object value)
{
if (value == null || IsSimpleType(value.GetType()))
{
return value;
}
if (value is HessianObject hessianObject)
{
if(TransferObjCache.TryGetValue(hessianObject.TypeName,out var properties))
{
var instance = Activator.CreateInstance(TransferTypeCache[hessianObject.TypeName]);
foreach (var (k, v) in hessianObject)
{
if (properties.TryGetValue(k, out var p))
{
p.SetValue(instance,GetRealObjectValue(deserializer,v));
}
}
return instance;
}
}
if (value is ClassDef)
{
return GetRealObjectValue(deserializer, deserializer.ReadValue());
}
if (IsListType(value.GetType()))
{
var listData = new List<object>();
var cList = value as List<object>;
foreach (var cItem in cList)
{
listData.Add(GetRealObjectValue(deserializer,cItem));
}
return listData;
}
throw new HessianException($"unknown item:{value.GetType()}");
}
private static bool IsListType(Type type)
{
return typeof(ICollection).IsAssignableFrom(type);
}
private static bool IsSimpleType(Type typeInfo)
{
if (typeInfo.IsValueType || typeInfo.IsEnum || typeInfo.IsPrimitive)
{
return true;
}
if (typeof (string) == typeInfo)
{
return true;
}
return false;
}
}
}

@ -1,79 +0,0 @@
using System;
using System.IO;
using DotXxlJob.Core.Model;
using Hessian;
namespace DotXxlJob.Core
{
public static class HessianSerializer
{
public static RpcRequest DeserializeRequest(Stream stream)
{
RpcRequest request = null;
try
{
var deserializer = new Deserializer(stream);
var classDef = deserializer.ReadValue() as ClassDef;
if (!Constants.RpcRequestJavaFullName.Equals(classDef.Name))
{
throw new HessianException($"unknown class :{classDef.Name}");
}
request = HessianObjectHelper.GetRealObjectValue(deserializer,deserializer.ReadValue()) as RpcRequest;
}
catch (EndOfStreamException)
{
//没有数据可读了
}
return request;
}
public static void SerializeRequest(Stream stream,RpcRequest req)
{
var serializer = new Serializer(stream);
serializer.WriteObject(req);
}
public static void SerializeResponse(Stream stream,RpcResponse res)
{
var serializer = new Serializer(stream);
serializer.WriteObject(res);
}
public static RpcResponse DeserializeResponse(Stream resStream)
{
RpcResponse rsp = null;
try
{
var deserializer = new Deserializer(resStream);
var classDef = deserializer.ReadValue() as ClassDef;
if (!Constants.RpcResponseJavaFullName.Equals(classDef.Name))
{
throw new HessianException($"unknown class :{classDef.Name}");
}
rsp = HessianObjectHelper.GetRealObjectValue(deserializer,deserializer.ReadValue()) as RpcResponse;
}
catch (EndOfStreamException)
{
//没有数据可读了
}
catch
{
//TODO: do something?
}
return rsp;
}
}
}

@ -5,8 +5,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DotXxlJob.Core.Config;
using DotXxlJob.Core.Extensions;
using DotXxlJob.Core.Model;
using Hessian;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

@ -4,7 +4,7 @@ namespace DotXxlJob.Core.Model
{
public class AddressEntry
{
public Uri RequestUri { get; set; }
public string RequestUri { get; set; }
private DateTime? LastFailedTime { get; set; }

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;
namespace DotXxlJob.Core.Model
{
[DataContract]
public class IdleBeatRequest
{
[DataMember(Name = "jobId", Order = 1)]
public int JobId { get; set; }
}
}

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;
namespace DotXxlJob.Core.Model
{
[DataContract]
public class KillRequest
{
[DataMember(Name = "jobId", Order = 1)]
public int JobId { get; set; }
}
}

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;
namespace DotXxlJob.Core.Model
{
[DataContract]
public class LogRequest
{
[DataMember(Name = "logDateTim", Order =1)]
public long LogDateTime { get; set; }
[DataMember(Name = "logId", Order = 2)]
public int LogId { get; set; }
[DataMember(Name = "fromLineNum", Order = 3)]
public int FromLineNum { get; set; }
}
}

@ -5,14 +5,14 @@ namespace DotXxlJob.Core.Model
[DataContract(Name = Constants.RegistryParamJavaFullName)]
public class RegistryParam
{
[DataMember(Name = "registGroup",Order = 1)]
[DataMember(Name = "registryGroup", Order = 1)]
public string RegistryGroup { get; set; }
[DataMember(Name = "registryKey",Order = 2)]
[DataMember(Name = "registryKey", Order = 2)]
public string RegistryKey { get; set; }
[DataMember(Name = "registryValue",Order = 3)]
[DataMember(Name = "registryValue", Order = 3)]
public string RegistryValue { get; set; }
}

@ -3,28 +3,28 @@ using System.Runtime.Serialization;
namespace DotXxlJob.Core.Model
{
[DataContract(Name = Constants.TriggerParamJavaFullName)]
[DataContract]
public class TriggerParam
{
//static readonly long SerialVersionUID = 42L;
[DataMember(Name = "jobId",Order = 1)]
[DataMember(Name = "jobId", Order = 1)]
public int JobId { get; set; }
[DataMember(Name = "executorHandler",Order = 2)]
[DataMember(Name = "executorHandler", Order = 2)]
public string ExecutorHandler { get; set; }
[DataMember(Name = "executorParams",Order = 3)]
[DataMember(Name = "executorParams", Order = 3)]
public string ExecutorParams{ get; set; }
[DataMember(Name = "executorBlockStrategy",Order = 4)]
[DataMember(Name = "executorBlockStrategy", Order = 4)]
public string ExecutorBlockStrategy{ get; set; }
[DataMember(Name = "executorTimeout",Order = 5)]
[DataMember(Name = "executorTimeout", Order = 5)]
public int ExecutorTimeout{ get; set; }
[DataMember(Name = "logId",Order = 5)]
public int LogId{ get; set; }
[DataMember(Name = "logDateTim",Order = 6)]
[DataMember(Name = "logDateTime", Order = 6)]
public long LogDateTime{ get; set; }
@ -34,7 +34,7 @@ namespace DotXxlJob.Core.Model
[DataMember(Name = "glueSource",Order = 8)]
public string GlueSource{ get; set; }
[DataMember(Name = "glueUpdatetime",Order = 9)]
[DataMember(Name = "glueUpdatetime", Order = 9)]
public long GlueUpdateTime{ get; set; }
[DataMember(Name = "broadcastIndex",Order = 10)]

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Cache;
using System.Text;
using System.Threading.Tasks;
using DotXxlJob.Core.Config;
using DotXxlJob.Core.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace DotXxlJob.Core
{
public class XxlRestfulServiceHandler
{
private readonly JobDispatcher _jobDispatcher;
private readonly IJobLogger _jobLogger;
private readonly ILogger<XxlRestfulServiceHandler> _logger;
private readonly XxlJobExecutorOptions _options;
public XxlRestfulServiceHandler(IOptions<XxlJobExecutorOptions> optionsAccessor,
JobDispatcher jobDispatcher,
IJobLogger jobLogger,
ILogger<XxlRestfulServiceHandler> logger)
{
this._jobDispatcher = jobDispatcher;
this._jobLogger = jobLogger;
this._logger = logger;
this._options = optionsAccessor.Value;
if (this._options == null)
{
throw new ArgumentNullException(nameof(XxlJobExecutorOptions));
}
}
public async Task HandlerAsync(HttpRequest request,HttpResponse response)
{
var path = request.Path.Value ;
ReturnT ret = null;
var arrParts = path.Split('/');
var method = arrParts[arrParts.Length - 1].ToLower();
if (!string.IsNullOrEmpty(this._options.AccessToken))
{
var reqToken = "";
if (request.Headers.TryGetValue("XXL-JOB-ACCESS-TOKEN", out var tokenValues))
{
reqToken = tokenValues[0].ToString();
}
if(this._options.AccessToken != reqToken)
{
ret = ReturnT.Failed("ACCESS-TOKEN Auth Fail");
response.ContentType = "application/json;charset=utf-8";
await response.WriteAsync(JsonConvert.SerializeObject(ret));
return;
}
}
try
{
string json = CollectBody(request.Body);
switch (method)
{
case "beat":
ret = Beat();
break;
case "idleBeat":
ret = IdleBeat(JsonConvert.DeserializeObject<IdleBeatRequest>(json));
break;
case "run":
ret = Run(JsonConvert.DeserializeObject<TriggerParam>(json));
break;
case "kill":
ret = Kill(JsonConvert.DeserializeObject<KillRequest>(json));
break;
case "log":
ret = Log(JsonConvert.DeserializeObject<LogRequest>(json));
break;
}
}
catch(Exception ex)
{
this._logger.LogError(ex,"响应出错"+ ex.Message);
ret = ReturnT.Failed("执行器内部错误");
}
if(ret == null)
{
ret = ReturnT.Failed($"method {method} is not impl");
}
response.ContentType = "application/json;charset=utf-8";
await response.WriteAsync(JsonConvert.SerializeObject(ret));
}
private string CollectBody(Stream body)
{
string bodyText;
using (var reader = new StreamReader(body))
{
bodyText = reader.ReadToEnd();
}
return bodyText;
}
#region rpc service
private ReturnT Beat()
{
return ReturnT.SUCCESS;
}
private ReturnT IdleBeat(IdleBeatRequest req)
{
if(req == null)
{
return ReturnT.Failed("IdleBeat Error");
}
return this._jobDispatcher.IdleBeat(req.JobId);
}
private ReturnT Kill(KillRequest req)
{
if (req == null)
{
return ReturnT.Failed("Kill Error");
}
return this._jobDispatcher.TryRemoveJobTask(req.JobId) ?
ReturnT.SUCCESS
:
ReturnT.Success("job thread already killed.");
}
/// <summary>
/// read Log
/// </summary>
/// <returns></returns>
private ReturnT Log(LogRequest req)
{
if (req == null)
{
return ReturnT.Failed("Log Error");
}
var ret = ReturnT.Success(null);
ret.Content = this._jobLogger.ReadLog(req.LogDateTime,req.LogId, req.FromLineNum);
return ret;
}
/// <summary>
/// 执行
/// </summary>
/// <param name="triggerParam"></param>
/// <returns></returns>
private ReturnT Run(TriggerParam triggerParam)
{
return this._jobDispatcher.Execute(triggerParam);
}
#endregion
}
}

@ -1,217 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Hessian;
using DotXxlJob.Core.Config;
using DotXxlJob.Core.Model;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace DotXxlJob.Core
{
/// <summary>
/// 负责执行Http请求,序列化和反序列化并发送响应
/// </summary>
public class XxlRpcServiceHandler
{
private readonly JobDispatcher _jobDispatcher;
private readonly IJobLogger _jobLogger;
private readonly ILogger<XxlRpcServiceHandler> _logger;
private readonly XxlJobExecutorOptions _options;
private readonly ConcurrentDictionary<string, MethodInfo> METHOD_CACHE =
new ConcurrentDictionary<string, MethodInfo>();
public XxlRpcServiceHandler(IOptions<XxlJobExecutorOptions> optionsAccessor,
JobDispatcher jobDispatcher,
IJobLogger jobLogger,
ILogger<XxlRpcServiceHandler> logger)
{
this._jobDispatcher = jobDispatcher;
this._jobLogger = jobLogger;
this._logger = logger;
this._options = optionsAccessor.Value;
if (this._options == null)
{
throw new ArgumentNullException(nameof(XxlJobExecutorOptions));
}
}
/// <summary>
/// 处理XxlRpc请求流
/// </summary>
/// <param name="reqStream"></param>
/// <returns></returns>
public async Task<byte[]> HandlerAsync(Stream reqStream)
{
var req = HessianSerializer.DeserializeRequest(reqStream);
var res = new RpcResponse { RequestId = req.RequestId};
if (!ValidRequest(req, out var error))
{
this._logger.LogWarning("job task request is not valid:{error}",error);
res.ErrorMsg = error;
}
else
{
this._logger.LogDebug("receive job task ,req.RequestId={requestId},method={methodName}"
,req.RequestId,req.MethodName);
await Invoke(req, res);
this._logger.LogDebug("completed receive job task ,req.RequestId={requestId},method={methodName},IsError={IsError}"
,req.RequestId,req.MethodName,res.IsError);
}
using (var outputStream = new MemoryStream())
{
HessianSerializer.SerializeResponse(outputStream,res);
return outputStream.GetBuffer();
}
}
/// <summary>
/// 校验请求信息
/// </summary>
/// <param name="req"></param>
/// <param name="error"></param>
/// <returns></returns>
private bool ValidRequest(RpcRequest req,out string error)
{
error = string.Empty;
if (req == null)
{
error = "unknown request stream data,codec fail";
return false;
}
if (!"com.xxl.job.core.biz.ExecutorBiz".Equals(req.ClassName)) //
{
error = "not supported request!";
return false;
}
if (DateTime.UtcNow.Subtract(req.CreateMillisTime.FromMilliseconds()) > Constants.RpcRequestExpireTimeSpan)
{
error = "request is timeout!";
return false;
}
if (!string.IsNullOrEmpty(this._options.AccessToken) && this._options.AccessToken != req.AccessToken)
{
error = "need authorize";
return false;
}
return true;
}
/// <summary>
/// 执行请求,获取执行函数
/// </summary>
/// <param name="req"></param>
/// <param name="res"></param>
/// <returns></returns>
private Task Invoke(RpcRequest req, RpcResponse res)
{
try
{
var method = GetMethodInfo(req.MethodName);
if (method == null)
{
res.ErrorMsg = $"The method{req.MethodName} is not defined.";
this._logger.LogWarning( $"The method{req.MethodName} is not defined.");
}
else
{
var result = method.Invoke(this, req.Parameters.ToArray());
res.Result = result;
}
}
catch (Exception ex)
{
res.ErrorMsg = ex.Message +"\n--------------\n"+ ex.StackTrace;
this._logger.LogError(ex,"invoke method error:{0}",ex.Message);
}
return Task.CompletedTask;
}
private MethodInfo GetMethodInfo(string methodName)
{
if (METHOD_CACHE.TryGetValue(methodName, out var method))
{
return method;
}
var type = GetType();
method = type.GetMethod( methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.IgnoreCase);
if (method != null)
{
METHOD_CACHE.TryAdd(methodName, method);
}
return method;
}
#region rpc service
private ReturnT Beat()
{
return ReturnT.SUCCESS;
}
private ReturnT IdleBeat(int jobId)
{
return this._jobDispatcher.IdleBeat(jobId);
}
private ReturnT Kill(int jobId)
{
return this._jobDispatcher.TryRemoveJobTask(jobId) ?
ReturnT.SUCCESS
:
ReturnT.Success("job thread already killed.");
}
/// <summary>
/// read Log
/// </summary>
/// <param name="logDateTime"></param>
/// <param name="logId"></param>
/// <param name="fromLineNum"></param>
/// <returns></returns>
private ReturnT Log(long logDateTime, int logId, int fromLineNum)
{
var ret = ReturnT.Success(null);
ret.Content = this._jobLogger.ReadLog(logDateTime, logId, fromLineNum);
return ret;
}
/// <summary>
/// 执行
/// </summary>
/// <param name="triggerParam"></param>
/// <returns></returns>
private ReturnT Run(TriggerParam triggerParam)
{
return this._jobDispatcher.Execute(triggerParam);
}
#endregion
}
}

@ -1,59 +0,0 @@
using System;
namespace Hessian
{
public class ClassDef : IEquatable<ClassDef>
{
public string Name { get; private set; }
public string[] Fields { get; private set; }
public ClassDef(string name, string[] fields)
{
Name = Conditions.CheckNotNull(name, "name");
Fields = Conditions.CheckNotNull(fields, "fields");
}
public override int GetHashCode()
{
unchecked {
const uint prime = 16777619;
var hash = 2166136261;
hash *= prime;
hash ^= (uint)Name.GetHashCode();
for (var i = 0; i < Fields.Length; ++i) {
hash *= prime;
hash ^= (uint)Fields[i].GetHashCode();
}
return (int)hash;
}
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != GetType()) {
return false;
}
return Equals((ClassDef) obj);
}
public bool Equals(ClassDef other)
{
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return string.Equals(Name, other.Name) && Fields.Equals(other.Fields);
}
}
}

@ -1,11 +0,0 @@
using System.Collections.Generic;
namespace Hessian
{
public class ClassElement
{
public string ClassName { get; set; }
public List<PropertyElement> Fields { get; set; }
}
}

@ -1,91 +0,0 @@
using System.Collections;
using System.Collections.Generic;
namespace Hessian.Collections
{
public abstract class ForwardingDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
protected abstract IDictionary<TKey, TValue> Delegate { get; }
public virtual ICollection<TKey> Keys
{
get { return Delegate.Keys; }
}
public virtual ICollection<TValue> Values
{
get { return Delegate.Values; }
}
public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return Delegate.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public virtual void Add(KeyValuePair<TKey, TValue> item)
{
Delegate.Add(item);
}
public virtual void Clear()
{
Delegate.Clear();
}
public virtual bool Contains(KeyValuePair<TKey, TValue> item)
{
return Delegate.Contains(item);
}
public virtual void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
Delegate.CopyTo(array, arrayIndex);
}
public virtual bool Remove(KeyValuePair<TKey, TValue> item)
{
return Delegate.Remove(item);
}
public virtual int Count
{
get { return Delegate.Count; }
}
public virtual bool IsReadOnly
{
get { return Delegate.IsReadOnly; }
}
public virtual bool ContainsKey(TKey key)
{
return Delegate.ContainsKey(key);
}
public virtual void Add(TKey key, TValue value)
{
Delegate.Add(key, value);
}
public virtual bool Remove(TKey key)
{
return Delegate.Remove(key);
}
public virtual bool TryGetValue(TKey key, out TValue value)
{
return Delegate.TryGetValue(key, out value);
}
public virtual TValue this[TKey key]
{
get { return Delegate[key]; }
set { Delegate[key] = value; }
}
}
}

@ -1,32 +0,0 @@
namespace Hessian.Collections
{
/// <summary>
/// Represents a map that associates objects with a zero-based integer
/// index. Specified in Hessian 2.0.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IRefMap<T>
{
/// <summary>
/// Adds an element to the ref map and returns its ID.
/// </summary>
/// <param name="entry"></param>
/// <returns></returns>
int Add(T entry);
/// <summary>
/// Retrieves the element identified by the given ID.
/// </summary>
/// <param name="refId"></param>
/// <returns></returns>
T Get(int refId);
/// <summary>
/// Looks up an element in the ref map and, if present, returns its ID.
/// </summary>
/// <remarks>
/// Performance of this method is not guaranteed and is implementation-specific.
/// </remarks>
int? Lookup(T entry);
}
}

@ -1,59 +0,0 @@
using System.Collections.Generic;
namespace Hessian.Collections
{
/// <summary>
/// Represents a dictionary which maintains uniqueness of both keys and values,
/// allowing for the lookup of a key by its value in additon to the normal
/// operations expected of a dictionary.
/// </summary>
public interface ITwoWayDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
/// <summary>
/// Exposes a view of the current dictionary that reverses keys and
/// values. Note that the same underlying data is shared.
/// </summary>
ITwoWayDictionary<TValue, TKey> Inverse { get; }
/// <summary>
/// Gets or sets a key by the given value.
/// </summary>
/// <param name="value">
/// The value with which to get or set a key.
/// </param>
/// <returns>
/// Returns the key indexing the given <paramref name="value"/>.
/// </returns>
TKey this[TValue valueKey] { get; set; }
/// <summary>
/// Gets a value indicating whether the given <paramref name="value"/>
/// is contained in this dictionary.
/// </summary>
/// <param name="value">
/// The value whose presence is to be determined.
/// </param>
/// <returns>
/// Returns <see langword="true"/> if <paramref name="value"/> is in
/// this dictionary, and <see langword="false"/> otherwise.
/// </returns>
bool ContainsValue(TValue value);
/// <summary>
/// Attempts to look up a key by the given value. A return value
/// indicates whether the lookip is successful.
/// </summary>
/// <param name="value">
/// The value whose corresponding key is to be retrieved.
/// </param>
/// <param name="key">
/// When the method returns, contains the looked-up key if the lookup
/// succeeded.
/// </param>
/// <returns>
/// Returns <see langword="true"/> if the lookup succeeded, and
/// <see langword="false"/> otherwise.
/// </returns>
bool TryGetKey(TValue value, out TKey key);
}
}

@ -1,34 +0,0 @@
using System.Collections.Generic;
namespace Hessian.Collections
{
public class ListRefMap<T> : IRefMap<T>
{
private readonly List<T> list = new List<T>();
public int Add(T entry)
{
list.Add(entry);
return list.Count - 1;
}
public T Get(int refId)
{
if (refId < 0 || refId >= list.Count) {
throw new InvalidRefException(refId);
}
return list[refId];
}
public int? Lookup(T entry)
{
for (var i = 0; i < list.Count; ++i) {
if (entry.Equals(list[i])) {
return i;
}
}
return null;
}
}
}

@ -1,123 +0,0 @@
using System.Collections.Generic;
namespace Hessian.Collections
{
public class TwoWayDictionary<TKey, TValue> : ForwardingDictionary<TKey, TValue>, ITwoWayDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> dict;
private readonly TwoWayDictionary<TValue, TKey> inverse;
protected override IDictionary<TKey, TValue> Delegate {
get { return dict; }
}
public override bool IsReadOnly {
get { return false; }
}
public ITwoWayDictionary<TValue, TKey> Inverse {
get { return inverse; }
}
public override TValue this[TKey key] {
set { UpdateDictAndInverse(key, value, false); }
}
public TKey this[TValue valueKey] {
get { return inverse[valueKey]; }
set { inverse[valueKey] = value; }
}
public override ICollection<TValue> Values {
get { return inverse.dict.Keys; }
}
public TwoWayDictionary()
: this(new Dictionary<TKey, TValue>(), new Dictionary<TValue, TKey>())
{
}
public TwoWayDictionary(IDictionary<TKey, TValue> forwards, IDictionary<TValue, TKey> backwards)
{
dict = Conditions.CheckNotNull(forwards, "forwards");
inverse = new TwoWayDictionary<TValue, TKey>(backwards, this);
}
private TwoWayDictionary(IDictionary<TKey, TValue> dict, TwoWayDictionary<TValue, TKey> inverse)
{
this.dict = Conditions.CheckNotNull(dict, "dict");
this.inverse = inverse;
}
public bool ContainsValue(TValue value)
{
return inverse.ContainsKey(value);
}
public bool TryGetKey(TValue value, out TKey key)
{
return inverse.TryGetValue(value, out key);
}
public override void Add(TKey key, TValue value)
{
UpdateDictAndInverse(key, value, true);
}
public override bool Remove(TKey key)
{
return RemoveFromDictAndInverse(key);
}
private void UpdateDictAndInverse(TKey key, TValue value, bool throwIfContained)
{
if (!throwIfContained) {
dict.Remove(key);
inverse.dict.Remove(value);
}
dict.Add(key, value);
inverse.dict.Add(value, key);
}
private bool RemoveFromDictAndInverse(TKey key)
{
TValue value;
if (!TryGetValue(key, out value)) {
return false;
}
return RemoveFromDictAndInverse(key, value);
}
private bool RemoveFromDictAndInverse(TKey key, TValue value)
{
if (!ContainsKey(key) || !ContainsValue(value)) {
return false;
}
return dict.Remove(key) && inverse.dict.Remove(value);
}
#region ICollection<KeyValuePair<TKey, TValue>>
public override bool Remove(KeyValuePair<TKey, TValue> kvp)
{
return RemoveFromDictAndInverse(kvp.Key, kvp.Value);
}
public override void Clear()
{
dict.Clear();
inverse.dict.Clear();
}
public override bool Contains(KeyValuePair<TKey, TValue> kvp)
{
return ContainsKey(kvp.Key) && ContainsValue(kvp.Value);
}
#endregion
}
}

@ -1,34 +0,0 @@
namespace Hessian.Collections
{
public class TwoWayDictionaryRefMap<T> : IRefMap<T>
{
private readonly TwoWayDictionary<T, int> map = new TwoWayDictionary<T, int>();
public int Add(T value)
{
var refid = map.Count;
map.Add(value, refid);
return refid;
}
public T Get(int refid)
{
T entry;
if (map.TryGetKey(refid, out entry)) {
return entry;
}
throw new InvalidRefException(refid);
}
public int? Lookup(T entry)
{
int refId;
if (map.TryGetValue(entry, out refId)) {
return refId;
}
return null;
}
}
}

@ -1,114 +0,0 @@
using System;
namespace Hessian
{
public class Conditions
{
protected Conditions()
{
}
public static void CheckArgument(bool condition, string message, params object[] args)
{
if (condition) {
return;
}
if (args.Length > 0) {
message = String.Format(message, args);
}
throw new ArgumentException(message);
}
public static T CheckNotNull<T>(T value, string name)
where T : class
{
if (!ReferenceEquals(value, null)) {
return value;
}
throw new ArgumentNullException(name);
}
public static TComparable CheckGreater<TComparable, TComparand>(TComparable value, TComparand bounds,
string name)
where TComparable : IComparable<TComparand>
{
if (value.CompareTo(bounds) > 0) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static TComparable CheckLess<TComparable, TComparand>(TComparable value, TComparand bounds,
string name)
where TComparable : IComparable<TComparand>
{
if (value.CompareTo(bounds) < 0) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static TComparable CheckGreaterOrEqual<TComparable, TComparand>(TComparable value, TComparand bounds,
string name)
where TComparable : IComparable<TComparand>
{
if (value.CompareTo(bounds) >= 0) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static TComparable CheckLessOrEqual<TComparable, TComparand>(TComparable value, TComparand bounds,
string name)
where TComparable : IComparable<TComparand>
{
if (value.CompareTo(bounds) <= 0) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static int CheckGreater(int value, int bounds, string name)
{
if (value > bounds) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static int CheckLess(int value, int bounds, string name)
{
if (value < bounds) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static int CheckGreaterOrEqual(int value, int bounds, string name)
{
if (value >= bounds) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
public static int CheckLessOrEqual(int value, int bounds, string name)
{
if (value <= bounds) {
return value;
}
throw new ArgumentOutOfRangeException(name);
}
}
}

File diff suppressed because it is too large Load Diff

@ -1,46 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hessian
{
public class DictionaryTypeResolver
{
private readonly Dictionary<string, Func<IDictionary<object, object>>> constructors;
public DictionaryTypeResolver()
{
constructors = new Dictionary<string, Func<IDictionary<object, object>>> {
{"System.Collections.Hashtable", DefaultCtor},
{"System.Collections.Generic.IDictionary`2", DefaultCtor},
{"System.Collections.Generic.Dictionary`2", DefaultCtor},
{"System.Collections.IDictionary", DefaultCtor},
{"java.lang.Map", DefaultCtor},
{"java.util.HashMap", DefaultCtor},
{"java.util.EnumMap", DefaultCtor},
{"java.util.TreeMap", DefaultCtor},
{"java.util.concurrent.ConcurrentHashMap", DefaultCtor}
};
}
public bool TryGetInstance(string type, out IDictionary<object, object> instance)
{
instance = null;
if (!constructors.TryGetValue(type, out var ctor)) {
return false;
}
instance = ctor();
return true;
}
private static IDictionary<object, object> DefaultCtor()
{
return new Dictionary<object, object>();
}
}
}

@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../build/version.props" />
<Import Project="../../build/releasenotes.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<DefineConstants>$(DefineConstants);DOTNETCORE</DefineConstants>
<Description>Hessian的编解码实现,并不完全哦</Description>
<Copyright>Xuanye @ 2018</Copyright>
<Authors>Xuanye</Authors>
<AssemblyTitle>Hession DotNet port</AssemblyTitle>
<AssemblyName>Hessian</AssemblyName>
<PackageId>Hessian</PackageId>
<Version>$(HessianPackageVersion)</Version>
<PackageTags>Hessian,xxl-job,protocol</PackageTags>
<PackageReleaseNotes>
$(HessianPackageNotes)
</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/xuanye/DotXxlJob</PackageProjectUrl>
<PackageLicense>https://github.com/xuanye/DotXxlJob/blob/master/LICENSE</PackageLicense>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/xuanye/DotXxlJob</RepositoryUrl>
</PropertyGroup>
</Project>

@ -1,24 +0,0 @@
using System;
namespace Hessian
{
public class HessianException : ApplicationException
{
public HessianException()
{
}
public HessianException(string message)
: base(message)
{
}
public HessianException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

@ -1,66 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Hessian
{
public class HessianObject : IReadOnlyCollection<Tuple<string, object>>
{
private readonly string typeName;
private readonly IDictionary<string, object> fields;
public string TypeName => typeName;
public object this[string key] => fields[key];
public int Count => fields.Count;
private HessianObject(string typeName)
{
this.typeName = Conditions.CheckNotNull(typeName, "typeName");
fields = new Dictionary<string, object>();
}
public IEnumerator<Tuple<string, object>> GetEnumerator()
{
return fields.Select(kvp => Tuple.Create(kvp.Key, kvp.Value)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public class Builder
{
private readonly HessianObject obj;
public HessianObject Object
{
get { return obj; }
}
private Builder(string typeName)
{
obj = new HessianObject(typeName);
}
public static Builder New(string typeName)
{
return new Builder(typeName);
}
public Builder Add(string field, object value)
{
obj.fields.Add(field, value);
return this;
}
public HessianObject Create()
{
return obj;
}
}
}
}

@ -1,27 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Hessian
{
public class HessianSerializationContext
{
public IList<Type> Classes
{
get;
private set;
}
public IList Instances
{
get;
private set;
}
public HessianSerializationContext()
{
Classes = new List<Type>();
Instances = new List<object>();
}
}
}

@ -1,15 +0,0 @@
using System;
namespace Hessian
{
public class InvalidRefException : HessianException
{
public int RefId { get; private set; }
public InvalidRefException(int refId)
: base(String.Format("Invalid ref ID: {0}", refId))
{
RefId = refId;
}
}
}

@ -1,66 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hessian
{
public class ListTypeResolver
{
private readonly Dictionary<string, Func<IList<object>>> constructors = new Dictionary<string, Func<IList<object>>>();
private readonly Dictionary<string, Func<int, IList<object>>> length_constructors = new Dictionary<string, Func<int, IList<object>>>();
private readonly Func<IList<object>> empty_list_ctor = () => new List<object>();
private readonly Func<int, IList<object>> empty_list_ctor_with_length = length => new List<object>(length);
public ListTypeResolver()
{
constructors.Add("System.Collections.ArrayList", empty_list_ctor);
constructors.Add("System.Collections.List", empty_list_ctor);
constructors.Add("System.Collections.IList", empty_list_ctor);
constructors.Add("System.Collections.Generic.List`1", empty_list_ctor);
constructors.Add("System.Collections.Generic.IList`1", empty_list_ctor);
constructors.Add("System.Collections.ObjectModel.Collection`1", () => new Collection<object>());
constructors.Add("java.util.List", empty_list_ctor);
constructors.Add("java.util.Vector", empty_list_ctor);
constructors.Add("java.util.ArrayList", empty_list_ctor);
constructors.Add("java.util.LinkedList", empty_list_ctor);
length_constructors.Add("System.Collections.List", empty_list_ctor_with_length);
length_constructors.Add("System.Collections.IList", empty_list_ctor_with_length);
length_constructors.Add("System.Collections.Generic.List`1", empty_list_ctor_with_length);
length_constructors.Add("System.Collections.Generic.IList`1", empty_list_ctor_with_length);
length_constructors.Add("java.util.List", empty_list_ctor_with_length);
length_constructors.Add("java.util.Vector", empty_list_ctor_with_length);
length_constructors.Add("java.util.ArrayList", empty_list_ctor_with_length);
length_constructors.Add("java.util.LinkedList", empty_list_ctor_with_length);
}
public bool TryGetListInstance(string type, out IList<object> list)
{
list = null;
Func<IList<object>> ctor;
if (!constructors.TryGetValue(type, out ctor)) {
return false;
}
list = ctor();
return true;
}
public bool TryGetListInstance(string type, int length, out IList<object> list)
{
list = null;
Func<int, IList<object>> ctor;
if (!length_constructors.TryGetValue(type, out ctor)) {
return false;
}
list = ctor(length);
return true;
}
}
}

@ -1,39 +0,0 @@
namespace Hessian
{
internal static class Marker
{
public const byte True = (byte) 'T';//0x54;
public const byte False = (byte) 'F';// 0x46;
public const byte Null = (byte) 'N';//0x4E;
public const byte BinaryNonfinalChunk = (byte) 'b';//0x41;
public const byte BinaryFinalChunk = (byte) 'B';//0x42;
public const byte ClassDefinition = (byte) 'C';//0x43;
public const byte DateTimeLong = 0x4A;
public const byte DateTimeCompact = 0x4B;
public const byte Double = 0x5A;
public const byte DoubleZero = 0x5B;
public const byte DoubleOne = 0x5C;
public const byte DoubleOctet = 0x5D;
public const byte DoubleShort = 0x5E;
public const byte DoubleFloat = 0x5F;
public const byte UnpackedInteger = (byte) 'I';// 0x49;
public const byte PackedLong = (byte) 'Y';// 0x59;
public const byte UnpackedLong = (byte) 'L';// 0x4C;
public const byte StringNonfinalChunk = 0x52;
public const byte StringFinalChunk = 0x53;
public const byte VarList = 0x55;
public const byte FixedList = 0x56;
public const byte VarListUntyped = 0x57;
public const byte FixListUntyped = 0x58;
public const byte CompactFixListStart = 0x70;
public const byte CompactFixListEnd = 0x77;
public const byte CompactFixListUntypedStart = 0x78;
public const byte CompactFixListUntypedEnd = 0x7F;
public const byte ClassReference = (byte) 'O';//0x4F
public const byte InstanceReference = (byte) 'Q'; //0x51;
}
}

@ -1,142 +0,0 @@
using System;
using System.IO;
namespace Hessian
{
public class PeekStream : Stream
{
private Stream inner;
private byte? peek;
public PeekStream(Stream inner)
{
if (inner == null) {
throw new ArgumentNullException("inner");
}
this.inner = inner;
this.peek = null;
}
public override bool CanRead {
get {
return inner.CanRead;
}
}
public override bool CanSeek {
get {
return false;
}
}
public override bool CanWrite {
get {
return false;
}
}
public override long Length {
get {
return inner.Length;
}
}
public override long Position {
get {
return inner.Position - (peek.HasValue ? 1 : 0);
}
set {
throw new NotSupportedException("Seeking not supported.");
}
}
public byte? Peek ()
{
if (!peek.HasValue) {
var b = inner.ReadByte();
if (b == -1) {
return null;
}
peek = (byte) b;
}
return peek;
}
public override int ReadByte ()
{
if (peek.HasValue) {
var val = peek.Value;
peek = null;
return val;
}
return inner.ReadByte();
}
public override int Read (byte[] buffer, int offset, int count)
{
Conditions.CheckNotNull(buffer, "buffer");
Conditions.CheckGreaterOrEqual(offset, 0, "offset");
Conditions.CheckLess(offset, buffer.Length, "offset");
Conditions.CheckGreaterOrEqual(count, 0, "count");
Conditions.CheckArgument(
offset + count <= buffer.Length,
"Buffer is not big enough to contain the requested amount of data at the given offset.");
if (count == 0) {
return 0;
}
var bytesToRead = count;
if (peek.HasValue) {
buffer[offset++] = peek.Value;
peek = null;
--bytesToRead;
}
int bytesRead;
while (bytesToRead > 0 && (bytesRead = inner.Read (buffer, offset, bytesToRead)) != 0) {
offset += bytesRead;
bytesToRead -= bytesRead;
}
return count - bytesToRead;
}
public override void Write (byte[] buffer, int offset, int count)
{
throw new NotSupportedException("Writes not supported.");
}
public override void SetLength (long value)
{
throw new NotSupportedException("Seeking not supported.");
}
public override long Seek (long offset, SeekOrigin origin)
{
throw new NotSupportedException("Seeking not supported.");
}
public override void Flush ()
{
throw new NotSupportedException("Writes not supported.");
}
protected override void Dispose (bool disposing)
{
if (inner != null) {
inner.Dispose ();
inner = null;
}
base.Dispose (disposing);
}
}
}

@ -1,25 +0,0 @@
namespace Hessian.Platform
{
public class BigEndianBitConverter : EndianBitConverter
{
protected override long FromBytes(byte[] bytes, int offset, int count)
{
var result = 0L;
for (var i = 0; i < count; ++i)
{
result = (result << 8) | bytes[offset + i];
}
return result;
}
protected override void CopyBytes(long source, byte[] buffer, int offset, int count)
{
var end = offset + count - 1;
for (var i = 0; i < count; ++i)
{
buffer[end - i] = (byte)(source & 0xFF);
source >>= 8;
}
}
}
}

@ -1,215 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Hessian.Platform
{
public abstract class EndianBitConverter
{
#region T -> byte[]
public byte[] GetBytes(bool value)
{
// One byte, no endianness
return BitConverter.GetBytes(value);
}
public byte[] GetBytes(char value)
{
return GetBytes(value, sizeof (char));
}
public byte[] GetBytes(short value)
{
return GetBytes(value, sizeof (short));
}
public byte[] GetBytes(ushort value)
{
return GetBytes(value, sizeof (ushort));
}
public byte[] GetBytes(int value)
{
return GetBytes(value, sizeof (int));
}
public byte[] GetBytes(uint value)
{
return GetBytes(value, sizeof (uint));
}
public byte[] GetBytes(long value)
{
return GetBytes(value, sizeof (long));
}
public byte[] GetBytes(ulong value)
{
return GetBytes((long)value, sizeof (ulong));
}
public byte[] GetBytes(float value)
{
return GetBytes(SingleToInt32(value), sizeof (int));
}
public byte[] GetBytes(double value)
{
return GetBytes(DoubleToInt64(value), sizeof (long));
}
private byte[] GetBytes(long value, int size)
{
var buffer = new byte[size];
CopyBytes(value, buffer, 0, size);
return buffer;
}
#endregion
#region byte[] -> T
public bool ToBoolean(byte[] value, int index)
{
// one byte, no endianness
return BitConverter.ToBoolean(value, index);
}
public char ToChar(byte[] value, int index)
{
return (char) FromBytes(value, index, sizeof (char));
}
public short ToInt16(byte[] value, int index)
{
return (short) FromBytes(value, index, sizeof (short));
}
public ushort ToUInt16(byte[] value, int index)
{
return (ushort) FromBytes(value, index, sizeof (ushort));
}
public int ToInt32(byte[] value, int index)
{
return (int) FromBytes(value, index, sizeof (int));
}
public uint ToUInt32(byte[] value, int index)
{
return (uint) FromBytes(value, index, sizeof (uint));
}
public long ToInt64(byte[] value, int index)
{
return FromBytes(value, index, sizeof (long));
}
public ulong ToUInt64(byte[] value, int index)
{
return (ulong) FromBytes(value, index, sizeof (ulong));
}
public float ToSingle(byte[] value, int index)
{
var int32 = (int) FromBytes(value, index, sizeof (int));
return Int32ToSingle(int32);
}
public double ToDouble(byte[] value, int index)
{
var int64 = FromBytes(value, index, sizeof (long));
return Int64ToDouble(int64);
}
#endregion
protected abstract long FromBytes(byte[] bytes, int offset, int count);
protected abstract void CopyBytes(long source, byte[] buffer, int index, int count);
private static int SingleToInt32(float value)
{
return new JonSkeetUnion32(value).AsInt;
}
private static float Int32ToSingle(int value)
{
return new JonSkeetUnion32(value).AsFloat;
}
private static long DoubleToInt64(double value)
{
return new JonSkeetUnion64(value).AsLong;
}
private static double Int64ToDouble(long value)
{
return new JonSkeetUnion64(value).AsDouble;
}
[StructLayout(LayoutKind.Explicit)]
private struct JonSkeetUnion32
{
[FieldOffset(0)]
private readonly int i;
[FieldOffset(0)]
private readonly float f;
public int AsInt
{
get { return i; }
}
public float AsFloat
{
get { return f; }
}
public JonSkeetUnion32(int value)
{
f = 0;
i = value;
}
public JonSkeetUnion32(float value)
{
i = 0;
f = value;
}
}
[StructLayout(LayoutKind.Explicit)]
private struct JonSkeetUnion64
{
[FieldOffset(0)]
private readonly long l;
[FieldOffset(0)]
private readonly double d;
public long AsLong
{
get { return l; }
}
public double AsDouble
{
get { return d; }
}
public JonSkeetUnion64(long value)
{
d = 0;
l = value;
}
public JonSkeetUnion64(double value)
{
l = 0;
d = value;
}
}
}
}

@ -1,25 +0,0 @@
namespace Hessian.Platform
{
public class LittleEndianBitConverter : EndianBitConverter
{
protected override long FromBytes(byte[] bytes, int offset, int count)
{
var result = 0L;
var end = offset + count - 1;
for (var i = 0; i < count; ++i)
{
result = (result << 8) | bytes[end - i];
}
return result;
}
protected override void CopyBytes(long source, byte[] buffer, int offset, int count)
{
for (var i = 0; i < count; ++i)
{
buffer[offset + i] = (byte)(source & 0xFF);
source >>= 8;
}
}
}
}

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Hessian
{
public class PropertyElement
{
public string Name { get; set; }
public int Order { get; set; }
public PropertyInfo PropertyInfo { get; set; }
}
internal class PropertyComparer : IComparer<PropertyElement>
{
private readonly IComparer<int> comparer;
public PropertyComparer()
{
comparer = Comparer<int>.Default;
}
public int Compare(PropertyElement x, PropertyElement y)
{
var eq = comparer.Compare(x.Order, y.Order);
return 0 == eq
? String.Compare(x.Name, y.Name, StringComparison.Ordinal)
: eq;
}
}
}

@ -1,523 +0,0 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;
namespace Hessian
{
public class Serializer
{
static readonly ConcurrentDictionary<Type,ClassElement> ClassDefCache =new ConcurrentDictionary<Type, ClassElement>();
private readonly Stream _stream;
private readonly HessianSerializationContext _context;
public Serializer (Stream stream)
{
this._stream = stream ?? throw new ArgumentNullException(nameof(stream));
_context = new HessianSerializationContext();
}
public void WriteObject(object graph)
{
var objectType = graph.GetType();
if (!ClassDefCache.TryGetValue(objectType, out var classDef))
{
classDef = GetClassDef(objectType.GetTypeInfo());
}
var index = this._context.Instances.IndexOf(graph);
if (index > -1)
{
WriteInstanceReference(index);
return;
}
this._context.Instances.Add(graph);
index = this._context.Classes.IndexOf(objectType);
if (index < 0)
{
BeginClassDefinition();
WriteString(classDef.ClassName);
WriteInt32(classDef.Fields.Count);
foreach (var property in classDef.Fields)
{
WriteString(property.Name);
}
EndClassDefinition();
index = this._context.Classes.Count;
this._context.Classes.Add(objectType);
}
WriteObjectReference(index);
foreach (var item in classDef.Fields)
{
var value = item.PropertyInfo.GetValue(graph);
WriteValue(value);
}
}
public void WriteValue(object val)
{
if (val == null)
{
WriteNull();
return;
}
var valType = val.GetType();
var typeInfo = valType.GetTypeInfo();
if (IsSimpleType(typeInfo))
{
WriteSimpleValue(val);
return;
}
if (IsListType(typeInfo))
{
WriteListValue(val);
return;
}
WriteObject(val);
}
private void WriteListValue(object val)
{
var tag = (int)Marker.CompactFixListStart;
if (!(val is ICollection eVal))
{
throw new HessianException("write list data error");
}
tag += eVal.Count;
if (tag > Marker.CompactFixListEnd)
{
throw new HessianException("write list data error,tag too large");
}
this._stream.WriteByte((byte)tag);
int index = 1;
foreach (var item in eVal)
{
if (index == 1)
{
WriteString("["+GetItemTypeName(item.GetType()));
}
WriteValue(item);
index++;
}
}
private string GetItemTypeName(Type type)
{
var classType = type.GetCustomAttribute<DataContractAttribute>();
if (classType != null)
{
return classType.Name;
}
if (IsListType(type.GetTypeInfo()))
{
return "java.util.List";
}
return type.Name;
}
private void WriteSimpleValue(object val)
{
var valType = val.GetType();
if (valType == typeof(int))
{
WriteInt32((int)val);
}
else if (valType == typeof(bool))
{
WriteBoolean((bool)val);
}
else if (valType == typeof(long))
{
WriteInt64((long)val);
}
else if (valType == typeof(double))
{
WriteDouble((double)val);
}
else if (valType == typeof(string))
{
WriteString((string)val);
}
else if (valType == typeof(DateTime))
{
WriteDateTime((DateTime)val);
}
}
private ClassElement GetClassDef(TypeInfo typeInfo)
{
var classAttr = typeInfo.GetCustomAttribute<DataContractAttribute>();
if (classAttr == null)
{
throw new HessianException("DataContract must be set");
}
ClassElement ce = new ClassElement {ClassName = classAttr.Name, Fields = new List<PropertyElement>()};
//ClassDef def = new ClassDef(classAttr.Name);
foreach (var property in typeInfo.DeclaredProperties)
{
var attribute = property.GetCustomAttribute<DataMemberAttribute>();
if (null == attribute)
{
continue;
}
if (!property.CanRead || !property.CanWrite)
{
continue;
}
PropertyElement p = new PropertyElement {
Name = attribute.Name,
Order = attribute.Order,
PropertyInfo = property
};
ce.Fields .Add( p );
}
ce.Fields.Sort(new PropertyComparer());
return ce;
}
/// <summary>
/// Writes NULL token into stream
/// </summary>
public void WriteNull()
{
this._stream.WriteByte(Marker.Null);
}
/// <summary>
/// Writes <see cref="System.Boolean" /> value into output stream.
/// </summary>
/// <param name="value">The value.</param>
public void WriteBoolean(bool value)
{
this._stream.WriteByte(value ? Marker.True : Marker.False);
}
/// <summary>
/// Writes array of <see cref="System.Byte" /> into output stream.
/// </summary>
/// <param name="buffer">The value.</param>
public void WriteBytes(byte[] buffer)
{
if (null == buffer)
{
WriteNull();
return;
}
WriteBytes(buffer, 0, buffer.Length);
}
public void WriteBytes(byte[] buffer, int offset, int count)
{
if (offset < 0)
{
throw new ArgumentException("", nameof(offset));
}
if (null == buffer)
{
WriteNull();
return;
}
if (count < 0x10)
{
this._stream.WriteByte((byte)(0x20 + (count & 0x0F)));
this._stream.Write(buffer, offset, count);
return;
}
const int chunkSize = 0x8000;
while (count > chunkSize)
{
this._stream.WriteByte(Marker.BinaryNonfinalChunk);
this._stream.WriteByte(chunkSize >> 8);
this._stream.WriteByte(chunkSize & 0xFF);
this._stream.Write(buffer, offset, chunkSize);
count -= chunkSize;
offset += chunkSize;
}
this._stream.WriteByte(Marker.BinaryFinalChunk);
this._stream.WriteByte((byte)(count >> 8));
this._stream.WriteByte((byte)(count & 0xFF));
this._stream.Write(buffer, offset, count);
}
public void WriteDateTime(DateTime value)
{
if (value.Second == 0)
{
var s = value.GetTotalMinutes();
this._stream.WriteByte(Marker.DateTimeCompact);
this._stream.WriteByte((byte)(s >> 24));
this._stream.WriteByte((byte)(s >> 16));
this._stream.WriteByte((byte)(s >> 8));
this._stream.WriteByte((byte)s);
return;
}
var dt = value.GetTotalMilliseconds();
this._stream.WriteByte(Marker.DateTimeLong);
this._stream.WriteByte((byte)(dt >> 56));
this._stream.WriteByte((byte)(dt >> 48));
this._stream.WriteByte((byte)(dt >> 40));
this._stream.WriteByte((byte)(dt >> 32));
this._stream.WriteByte((byte)(dt >> 24));
this._stream.WriteByte((byte)(dt >> 16));
this._stream.WriteByte((byte)(dt >> 8));
this._stream.WriteByte((byte)dt);
}
public void WriteDouble(double value)
{
if (value.Equals(0.0d))
{
this._stream.WriteByte(Marker.DoubleZero);
return;
}
if (value.Equals(1.0d))
{
this._stream.WriteByte(Marker.DoubleOne);
return;
}
var fraction = Math.Abs(value - Math.Truncate(value));
if (Double.Epsilon >= fraction)
{
if (Byte.MinValue <= value && value <= Byte.MaxValue)
{
this._stream.WriteByte(Marker.DoubleOctet);
this._stream.WriteByte(Convert.ToByte(value));
return;
}
if (Int16.MinValue <= value && value <= Int16.MaxValue)
{
var val = Convert.ToInt16(value);
this._stream.WriteByte(Marker.DoubleShort);
this._stream.WriteByte((byte)(val >> 8));
this._stream.WriteByte((byte)val);
return;
}
}
if (Single.MinValue <= value && value <= Single.MaxValue)
{
var bytes = BitConverter.GetBytes((float) value);
this._stream.WriteByte(Marker.DoubleFloat);
for (var index = bytes.Length - 1; index >= 0; index--)
{
this._stream.WriteByte(bytes[index]);
}
return;
}
var temp = BitConverter.DoubleToInt64Bits(value);
this._stream.WriteByte(Marker.Double);
for (var index = 56; index >= 0; index -= 8)
{
this._stream.WriteByte((byte) (temp >> index));
}
}
public void WriteInt32(int value)
{
if (-16 <= value && value < 48)
{
this._stream.WriteByte((byte)(0x90 + value));
}
else if (-2048 <= value && value < 2048)
{
this._stream.WriteByte((byte)(0xC8 + (byte)(value >> 8)));
this._stream.WriteByte((byte)value);
}
else if (-262144 <= value && value < 262144)
{
this._stream.WriteByte((byte)(0xD4 + (byte)(value >> 16)));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
else
{
this._stream.WriteByte(Marker.UnpackedInteger);
this._stream.WriteByte((byte)(value >> 24));
this._stream.WriteByte((byte)(value >> 16));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
}
public void WriteInt64(long value)
{
if (-8 <= value && value < 16)
{
this._stream.WriteByte((byte)(0xE0 + value));
}
else if (-2048 <= value && value < 2048)
{
this._stream.WriteByte((byte)(0xF8 + (byte)(value >> 8)));
this._stream.WriteByte((byte)value);
}
else if (-262144 <= value && value < 262144)
{
this._stream.WriteByte((byte)(0x3C + (byte)(value >> 16)));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
else if (Int32.MinValue <= value && value <= Int32.MaxValue)
{
this._stream.WriteByte(Marker.PackedLong);
this._stream.WriteByte((byte)(value >> 24));
this._stream.WriteByte((byte)(value >> 16));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
else
{
this._stream.WriteByte(Marker.UnpackedLong);
this._stream.WriteByte((byte)(value >> 56));
this._stream.WriteByte((byte)(value >> 48));
this._stream.WriteByte((byte)(value >> 40));
this._stream.WriteByte((byte)(value >> 32));
this._stream.WriteByte((byte)(value >> 24));
this._stream.WriteByte((byte)(value >> 16));
this._stream.WriteByte((byte)(value >> 8));
this._stream.WriteByte((byte)value);
}
}
public void WriteString(string value)
{
if (string.IsNullOrEmpty(value))
{
this._stream.WriteByte(0x00);
return;
}
var length = value.Length;
if (1024 > length)
{
var bytes = Encoding.UTF8.GetBytes(value.ToCharArray());
if (32 > length)
{
this._stream.WriteByte((byte) length);
}
else
{
this._stream.WriteByte((byte) (0x30 + (byte) (length >> 8)));
this._stream.WriteByte((byte) length);
}
this._stream.Write(bytes, 0, bytes.Length);
return;
}
const int maxChunkLength = 1024;
var position = 0;
while (position < length)
{
var count = Math.Min(length - position, maxChunkLength);
var final = length == (position + count);
var chunk = value.Substring(position, count);
var bytes = Encoding.UTF8.GetBytes(chunk.ToCharArray());
this._stream.WriteByte(final ? Marker.StringFinalChunk : Marker.StringNonfinalChunk);
this._stream.WriteByte((byte)(count >> 8));
this._stream.WriteByte((byte)count);
this._stream.Write(bytes, 0, bytes.Length);
position += count;
}
}
public void BeginClassDefinition()
{
this._stream.WriteByte(Marker.ClassDefinition);
}
public void EndClassDefinition()
{
}
public void WriteObjectReference(int index)
{
if (index < 0x10)
{
this._stream.WriteByte((byte)(0x60 + index));
}
else
{
this._stream.WriteByte(Marker.ClassReference);
WriteInt32(index);
}
}
public void WriteInstanceReference(int index)
{
this._stream.WriteByte(Marker.InstanceReference);
WriteInt32(index);
}
private static bool IsSimpleType(TypeInfo typeInfo)
{
if (typeInfo.IsValueType || typeInfo.IsEnum || typeInfo.IsPrimitive)
{
return true;
}
if (typeof (String) == typeInfo.AsType())
{
return true;
}
return false;
}
private static bool IsListType(TypeInfo typeInfo)
{
return typeof(ICollection).IsAssignableFrom(typeInfo);
}
}
}

@ -1,39 +0,0 @@
using System;
using System.IO;
using System.Text;
namespace Hessian
{
public static class StringBuilderExtensions
{
public static StringBuilder AppendCodepoint(this StringBuilder sb, uint codepoint)
{
if (codepoint < 0x10000) {
return sb.Append((char)codepoint);
}
var n = codepoint - 0x10000;
var high = (char)((n >> 10) + 0xD800);
var low = (char)((n & 0x3FF) + 0xDC00);
AssertValidSurrogates(high, low);
return sb
.Append (high)
.Append (low);
}
[System.Diagnostics.Conditional("DEBUG")]
private static void AssertValidSurrogates (char high, char low)
{
if (!Char.IsHighSurrogate (high)) {
throw new InvalidDataException ("Invalid high surrogate");
}
if (!Char.IsLowSurrogate (low)) {
throw new InvalidDataException ("Invalid low surrogate");
}
}
}
}

@ -1,18 +0,0 @@
namespace Hessian
{
public class UnexpectedTagException : HessianException
{
public byte Tag { get; private set; }
public UnexpectedTagException(byte tag, string expectedType)
: base(FormatErrorMessage(tag, expectedType))
{
Tag = tag;
}
private static string FormatErrorMessage(byte tag, string expectedType)
{
return string.Format("{0:X} is not a valid {1} tag.", tag, expectedType);
}
}
}

@ -1,163 +0,0 @@
using System;
using System.IO;
namespace Hessian
{
public class ValueReader
{
private byte[] buffer = new byte[8];
private PeekStream stream;
public ValueReader (Stream stream)
{
this.stream = stream as PeekStream ?? new PeekStream(stream);
}
public byte? Peek ()
{
return stream.Peek ();
}
public short ReadShort ()
{
Read (buffer, 0, 2);
return BitConverter.ToInt16(buffer, 0);
}
public int ReadInt()
{
Read (buffer, 0, 4);
return BitConverter.ToInt32(buffer, 0);
}
public uint ReadUtf8Codepoint ()
{
const uint replacementChar = 0xFFFD;
byte b0, b1, b2, b3;
b0 = ReadByte ();
if (b0 < 0x80) {
return b0;
}
if (b0 < 0xC2) {
return replacementChar;
}
if (b0 < 0xE0) {
b1 = ReadByte ();
if ((b1 ^ 0x80) >= 0x40) {
return replacementChar;
}
return (b1 & 0x3Fu) | ((b0 & 0x1Fu) << 6);
}
if (b0 < 0xF0) {
b1 = ReadByte ();
b2 = ReadByte ();
// Valid range: E0 A0..BF 80..BF
if (b0 == 0xE0 && (b1 ^ 0xA0) >= 0x20) {
return replacementChar;
}
// Valid range: ED 80..9F 80..BF
if (b0 == 0xED && (b1 ^ 0x80) >= 0x20) {
return replacementChar;
}
// Valid range: E1..EC 80..BF 80..BF
if ((b1 ^ 0x80) >= 0x40 || (b2 ^ 0x80) >= 0x40) {
return replacementChar;
}
return (b2 & 0x3Fu)
| ((b1 & 0x3Fu) << 6)
| ((b0 & 0x0Fu) << 12);
}
if (b0 < 0xF1) {
b1 = ReadByte();
if ((b1 ^ 0x90) < 0x30) {
return replacementChar;
}
b2 = ReadByte();
b3 = ReadByte();
if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
return replacementChar;
}
return (b3 & 0x3Fu)
| ((b2 & 0x3Fu) << 6)
| ((b1 & 0x3Fu) << 12)
| ((b0 & 0x07u) << 18);
}
if (b0 < 0xF4) {
b1 = ReadByte ();
b2 = ReadByte ();
b3 = ReadByte ();
// Valid range: F1..F3 80..BF 80..BF 80..BF
if ((b1 & 0xC0) != 0x80 || (b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80)
{
return replacementChar;
}
return (b3 & 0x3Fu)
| ((b2 & 0x3Fu) << 6)
| ((b1 & 0x3Fu) << 12)
| ((b0 & 0x07u) << 18);
}
if (b0 < 0xF5) {
b1 = ReadByte ();
// Valid range: F4 80..8F 80..BF 80..BF
if ((b1 ^ 0x80) >= 0x10) {
return replacementChar;
}
b2 = ReadByte();
b3 = ReadByte();
if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80)
{
return replacementChar;
}
return (b3 & 0x3Fu)
| ((b2 & 0x3Fu) << 6)
| ((b1 & 0x3Fu) << 12)
| ((b0 & 0x07u) << 18);
}
return replacementChar;
}
public byte ReadByte()
{
var b = stream.ReadByte();
if (b == -1) throw new EndOfStreamException();
return (byte)b;
}
public void Read(byte[] buffer, int count)
{
Read (buffer, 0, count);
}
private void Read(byte[] buffer, int offset, int count)
{
var bytesRead = stream.Read (buffer, offset, count);
if (bytesRead != count) throw new EndOfStreamException();
}
}
}

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Hessian\Hessian.csproj" />
</ItemGroup>
</Project>

@ -1,13 +0,0 @@
using System;
using Xunit;
namespace Hessian.Tests
{
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}
}
Loading…
Cancel
Save