parent
db29347e37
commit
e2d82ae952
63 changed files with 333 additions and 4107 deletions
@ -1,10 +1,7 @@ |
|||||||
<Project> |
<Project> |
||||||
<PropertyGroup> |
<PropertyGroup> |
||||||
<DotXxlJobPackageNotes> |
<DotXxlJobPackageNotes> |
||||||
1. 修复回调一次过多的问题 |
1. 修改接口方式为Restful方式,适配xxl-jobv2.2以上版本 |
||||||
</DotXxlJobPackageNotes> |
</DotXxlJobPackageNotes> |
||||||
<HessianPackageNotes> |
|
||||||
1. 实现基本的Hessian协议 |
|
||||||
</HessianPackageNotes> |
|
||||||
</PropertyGroup> |
</PropertyGroup> |
||||||
</Project> |
</Project> |
||||||
|
|||||||
@ -1,6 +1,5 @@ |
|||||||
<Project> |
<Project> |
||||||
<PropertyGroup> |
<PropertyGroup> |
||||||
<DotXxlJobPackageVersion>1.0.8</DotXxlJobPackageVersion> |
<DotXxlJobPackageVersion>2.0.0</DotXxlJobPackageVersion> |
||||||
<HessianPackageVersion>1.0.1</HessianPackageVersion> |
|
||||||
</PropertyGroup> |
</PropertyGroup> |
||||||
</Project> |
</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"}]}] |
|
||||||
------------------------------------------------------------ |
|
||||||
------------------------------------------------------------ |
|
||||||
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 |
|
||||||
@ -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; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
||||||
@ -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,11 +0,0 @@ |
|||||||
using System.Collections.Generic; |
|
||||||
|
|
||||||
namespace Hessian |
|
||||||
{ |
|
||||||
public class ClassElement |
|
||||||
{ |
|
||||||
public string ClassName { get; set; } |
|
||||||
|
|
||||||
public List<PropertyElement> Fields { get; set; } |
|
||||||
} |
|
||||||
} |
|
||||||
File diff suppressed because it is too large
Load Diff
@ -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,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,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,13 +0,0 @@ |
|||||||
using System; |
|
||||||
using Xunit; |
|
||||||
|
|
||||||
namespace Hessian.Tests |
|
||||||
{ |
|
||||||
public class UnitTest1 |
|
||||||
{ |
|
||||||
[Fact] |
|
||||||
public void Test1() |
|
||||||
{ |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue