From 8b8aba2f9ede021f4951e51093b2891969ede733 Mon Sep 17 00:00:00 2001 From: Frank Wagner Date: Thu, 21 Mar 2024 08:43:30 +0100 Subject: [PATCH] Added IO for global library functions (#284) new Trait HasSAPRfcLibrary with RfcLibraryIO --- YaNco.sln.DotSettings | 1 + .../SAPRfcRuntimeSettings.cs | 1 + .../Traits/HasSAPRfcLibrary.cs | 13 ++++ .../Traits/SAPRfcLibraryIO.cs | 17 ++++++ src/YaNco.Core/Internal/Api.cs | 36 ++++++++++- src/YaNco.Core/Internal/Interopt.cs | 26 +++++++- src/YaNco.Core/Live/IOResult.cs | 15 +++++ src/YaNco.Core/Live/LiveSAPRfcLibraryIO.cs | 59 +++++++++++++++++++ src/YaNco.Core/Live/LiveSAPRfcServerIO.cs | 1 - src/YaNco.Core/Live/SAPRfcRuntime.cs | 7 ++- src/YaNco.Core/Test/TestSAPRfcRuntime.cs | 4 ++ test/SAPSystemTests/Program.cs | 12 ++++ 12 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 src/YaNco.Abstractions/Traits/HasSAPRfcLibrary.cs create mode 100644 src/YaNco.Abstractions/Traits/SAPRfcLibraryIO.cs create mode 100644 src/YaNco.Core/Live/LiveSAPRfcLibraryIO.cs diff --git a/YaNco.sln.DotSettings b/YaNco.sln.DotSettings index 541e2c42..0fef0f99 100644 --- a/YaNco.sln.DotSettings +++ b/YaNco.sln.DotSettings @@ -7,6 +7,7 @@ True True True + True True True True diff --git a/src/YaNco.Abstractions/SAPRfcRuntimeSettings.cs b/src/YaNco.Abstractions/SAPRfcRuntimeSettings.cs index 94c1d16e..094a5779 100644 --- a/src/YaNco.Abstractions/SAPRfcRuntimeSettings.cs +++ b/src/YaNco.Abstractions/SAPRfcRuntimeSettings.cs @@ -53,4 +53,5 @@ public SAPRfcRuntimeSettings(ILogger logger, IFieldMapper fieldMapper, RfcRuntim public SAPRfcFunctionIO RfcFunctionIO { get; set; } public SAPRfcConnectionIO RfcConnectionIO { get; set; } public SAPRfcServerIO RfcServerIO { get; set; } + public SAPRfcLibraryIO RfcLibraryIO { get; set; } } \ No newline at end of file diff --git a/src/YaNco.Abstractions/Traits/HasSAPRfcLibrary.cs b/src/YaNco.Abstractions/Traits/HasSAPRfcLibrary.cs new file mode 100644 index 00000000..8f043827 --- /dev/null +++ b/src/YaNco.Abstractions/Traits/HasSAPRfcLibrary.cs @@ -0,0 +1,13 @@ +using JetBrains.Annotations; +using LanguageExt; + +namespace Dbosoft.YaNco.Traits; + +[PublicAPI] +// ReSharper disable once InconsistentNaming +public interface HasSAPRfcLibrary : IHasEnvRuntimeSettings + where RT : struct +{ + Eff RfcLibraryEff { get; } + +} \ No newline at end of file diff --git a/src/YaNco.Abstractions/Traits/SAPRfcLibraryIO.cs b/src/YaNco.Abstractions/Traits/SAPRfcLibraryIO.cs new file mode 100644 index 00000000..0f7001ca --- /dev/null +++ b/src/YaNco.Abstractions/Traits/SAPRfcLibraryIO.cs @@ -0,0 +1,17 @@ +using LanguageExt; + +namespace Dbosoft.YaNco.Traits; + +// ReSharper disable once InconsistentNaming +public interface SAPRfcLibraryIO +{ + Either GetVersion(); + Either SetTraceDirectory(string traceDirectory); + Either SetMaximumTraceFiles(int traceFiles); + Either SetCpicTraceLevel(int traceLevel); + + Either LoadCryptoLibrary(string libraryPath); + Either SetIniDirectory(string iniDirectory); + Either ReloadRfcIni(); + +} \ No newline at end of file diff --git a/src/YaNco.Core/Internal/Api.cs b/src/YaNco.Core/Internal/Api.cs index d41336bd..d0935eb3 100644 --- a/src/YaNco.Core/Internal/Api.cs +++ b/src/YaNco.Core/Internal/Api.cs @@ -9,7 +9,41 @@ namespace Dbosoft.YaNco.Internal; [ExcludeFromCodeCoverage] public static class Api { - + public static Version GetVersion() + { + _ = Interopt.RfcGetVersion(out var major, out var minor, out var patch); + return new Version((int) major, (int) minor, (int) patch); + } + + public static RfcRc SetTraceDirectory(string traceDirectory, out RfcErrorInfo errorInfo) + { + return Interopt.RfcSetTraceDir(traceDirectory, out errorInfo); + } + public static RfcRc SetMaximumTraceFiles(int maxTraceFiles, out RfcErrorInfo errorInfo) + { + return Interopt.RfcSetMaximumStoredTraceFiles(maxTraceFiles, out errorInfo); + } + + public static RfcRc SetCpicTraceLevel(int traceLevel, out RfcErrorInfo errorInfo) + { + return Interopt.RfcSetCpicTraceLevel((uint) traceLevel, out errorInfo); + } + + public static RfcRc SetIniDirectory(string iniDirectory, out RfcErrorInfo errorInfo) + { + return Interopt.RfcSetIniPath(iniDirectory, out errorInfo); + } + + public static RfcRc ReloadIniFile(out RfcErrorInfo errorInfo) + { + return Interopt.RfcReloadIniFile(out errorInfo); + } + + public static RfcRc LoadCryptoLibrary(string libraryPath, out RfcErrorInfo errorInfo) + { + return Interopt.RfcLoadCryptoLibrary(libraryPath, out errorInfo); + } + public static ConnectionHandle OpenConnection(IDictionary connectionParams, out RfcErrorInfo errorInfo) { diff --git a/src/YaNco.Core/Internal/Interopt.cs b/src/YaNco.Core/Internal/Interopt.cs index ca09538c..6a38f05a 100644 --- a/src/YaNco.Core/Internal/Interopt.cs +++ b/src/YaNco.Core/Internal/Interopt.cs @@ -1,8 +1,12 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + // ReSharper disable IdentifierTypo // ReSharper disable CommentTypo +// ReSharper disable InconsistentNaming namespace Dbosoft.YaNco.Internal; @@ -12,9 +16,29 @@ internal static class Interopt private const string SapNwRfcName = "sapnwrfc"; [DllImport(SapNwRfcName)] - public static extern RfcRc RfcGetVersion(out uint majorVersion, out uint minorVersion, out uint patchLevel); + public static extern IntPtr RfcGetVersion(out uint majorVersion, out uint minorVersion, out uint patchLevel); + + [DllImport(SapNwRfcName, CharSet = CharSet.Unicode)] + public static extern RfcRc RfcSetTraceDir(string traceDir, out RfcErrorInfo errorInfo); + + + [DllImport(SapNwRfcName)] + public static extern RfcRc RfcSetMaximumStoredTraceFiles(int numberOfFiles, out RfcErrorInfo errorInfo); + [DllImport(SapNwRfcName)] + public static extern RfcRc RfcSetCpicTraceLevel(uint traceLevel, out RfcErrorInfo errorInfo); + + + [DllImport(SapNwRfcName, CharSet = CharSet.Unicode)] + public static extern RfcRc RfcLoadCryptoLibrary(string pathToLibrary, out RfcErrorInfo errorInfo); + + [DllImport(SapNwRfcName, CharSet = CharSet.Unicode)] + public static extern RfcRc RfcSetIniPath(string pathName, out RfcErrorInfo errorInfo); + + [DllImport(SapNwRfcName)] + public static extern RfcRc RfcReloadIniFile(out RfcErrorInfo errorInfo); + [DllImport(SapNwRfcName, CharSet = CharSet.Unicode)] public static extern IntPtr RfcOpenConnection(RfcConnectionParameter[] connectionParams, uint paramCount, out RfcErrorInfo errorInfo); diff --git a/src/YaNco.Core/Live/IOResult.cs b/src/YaNco.Core/Live/IOResult.cs index 650fb059..49ac1bd1 100644 --- a/src/YaNco.Core/Live/IOResult.cs +++ b/src/YaNco.Core/Live/IOResult.cs @@ -49,4 +49,19 @@ public static Either ResultOrError( logger.IfSome(l => l.LogTrace("received result value from rfc call", result)); return result; } + + public static Either ResultOrError( + Option logger, + TResult result, RfcRc rc) + { + if (rc != RfcRc.RFC_OK) + { + logger.IfSome(l => l.LogDebug("received error from rfc call", + rc)); + return RfcError.Error(rc); + } + + logger.IfSome(l => l.LogTrace("received result value from rfc call", result)); + return result; + } } \ No newline at end of file diff --git a/src/YaNco.Core/Live/LiveSAPRfcLibraryIO.cs b/src/YaNco.Core/Live/LiveSAPRfcLibraryIO.cs new file mode 100644 index 00000000..c0d9b6ca --- /dev/null +++ b/src/YaNco.Core/Live/LiveSAPRfcLibraryIO.cs @@ -0,0 +1,59 @@ +using System; +using Dbosoft.YaNco.Internal; +using Dbosoft.YaNco.Traits; +using LanguageExt; + +namespace Dbosoft.YaNco.Live; + +public readonly struct LiveSAPRfcLibraryIO : SAPRfcLibraryIO +{ + private readonly Option _logger; + + public LiveSAPRfcLibraryIO(Option logger) + { + _logger = logger; + } + + public Either GetVersion() + { + return Prelude.Try(Api.GetVersion).ToEither(f => RfcError.New(f)); + + } + + public Either SetTraceDirectory(string traceDirectory) + { + var rc = Api.SetTraceDirectory(traceDirectory, out var errorInfo); + return IOResult.ResultOrError(_logger, Unit.Default, rc, errorInfo); + } + + public Either SetMaximumTraceFiles(int traceFiles) + { + var rc = Api.SetMaximumTraceFiles(traceFiles, out var errorInfo); + return IOResult.ResultOrError(_logger, Unit.Default, rc, errorInfo); + } + + public Either SetCpicTraceLevel(int traceLevel) + { + var rc = Api.SetCpicTraceLevel(traceLevel, out var errorInfo); + return IOResult.ResultOrError(_logger, Unit.Default, rc, errorInfo); + } + + public Either LoadCryptoLibrary(string libraryPath) + { + var rc = Api.LoadCryptoLibrary(libraryPath, out var errorInfo); + return IOResult.ResultOrError(_logger, Unit.Default, rc, errorInfo); + } + + public Either SetIniDirectory(string iniDirectory) + { + var rc = Api.SetIniDirectory(iniDirectory, out var errorInfo); + return IOResult.ResultOrError(_logger, Unit.Default, rc, errorInfo); + } + + public Either ReloadRfcIni() + { + var rc = Api.ReloadIniFile(out var errorInfo); + return IOResult.ResultOrError(_logger, Unit.Default, rc, errorInfo); + } + +} \ No newline at end of file diff --git a/src/YaNco.Core/Live/LiveSAPRfcServerIO.cs b/src/YaNco.Core/Live/LiveSAPRfcServerIO.cs index 905bf8b5..bd272c7e 100644 --- a/src/YaNco.Core/Live/LiveSAPRfcServerIO.cs +++ b/src/YaNco.Core/Live/LiveSAPRfcServerIO.cs @@ -6,7 +6,6 @@ namespace Dbosoft.YaNco.Live; - public readonly struct LiveSAPRfcServerIO : SAPRfcServerIO { private readonly Option _logger; diff --git a/src/YaNco.Core/Live/SAPRfcRuntime.cs b/src/YaNco.Core/Live/SAPRfcRuntime.cs index 90678390..d90025b4 100644 --- a/src/YaNco.Core/Live/SAPRfcRuntime.cs +++ b/src/YaNco.Core/Live/SAPRfcRuntime.cs @@ -12,7 +12,8 @@ namespace Dbosoft.YaNco.Live; /// public readonly struct SAPRfcRuntime - : HasSAPRfc, + : HasSAPRfc, + HasSAPRfcLibrary, HasSAPRfcServer, HasCancel @@ -84,6 +85,7 @@ public static SAPRfcRuntime New(CancellationTokenSource cancellationTokenSource, private SAPRfcFunctionIO FunctionIO => Env.Settings.RfcFunctionIO ?? new LiveSAPRfcFunctionIO(Logger, DataIO); private SAPRfcConnectionIO ConnectionIO => Env.Settings.RfcConnectionIO ?? new LiveSAPRfcConnectionIO(Logger); private SAPRfcServerIO ServerIO => Env.Settings.RfcServerIO ?? new LiveSAPRfcServerIO(Logger); + private SAPRfcLibraryIO LibraryIO => Env.Settings.RfcLibraryIO ?? new LiveSAPRfcLibraryIO(Logger); public Eff> RfcLoggerEff => Prelude.Eff>(rt => rt.Logger); @@ -102,4 +104,7 @@ public static SAPRfcRuntime New(CancellationTokenSource cancellationTokenSource, public Eff FieldMapperEff => Prelude.Eff < SAPRfcRuntime, IFieldMapper>( rt => rt.Env.Settings.FieldMapper); + + public Eff RfcLibraryEff => Prelude.Eff( + rt => rt.LibraryIO); } \ No newline at end of file diff --git a/src/YaNco.Core/Test/TestSAPRfcRuntime.cs b/src/YaNco.Core/Test/TestSAPRfcRuntime.cs index a61ef07d..e15e3e94 100644 --- a/src/YaNco.Core/Test/TestSAPRfcRuntime.cs +++ b/src/YaNco.Core/Test/TestSAPRfcRuntime.cs @@ -11,6 +11,7 @@ public readonly struct TestSAPRfcRuntime : HasSAPRfcServer, HasSAPRfc, + HasSAPRfcLibrary, HasCancel { private readonly SAPRfcRuntimeEnv _env; @@ -84,4 +85,7 @@ public static TestSAPRfcRuntime New(Action configure) public Eff FieldMapperEff => Prelude.Eff( rt => rt.Env.Settings.FieldMapper); + + public Eff RfcLibraryEff => Prelude.Eff( + rt => rt.Env.Settings.RfcLibraryIO); } \ No newline at end of file diff --git a/test/SAPSystemTests/Program.cs b/test/SAPSystemTests/Program.cs index 6da1de9a..c8af2382 100644 --- a/test/SAPSystemTests/Program.cs +++ b/test/SAPSystemTests/Program.cs @@ -123,6 +123,18 @@ from call in invokeFunction(c, "ZYANCO_IT_3") // functional style Tests: + // library tests + var libVersion = SAPRfcRuntime.Default.RfcLibraryEff.Bind(io => + { + return ( + from _ in io.SetTraceDirectory(AppDomain.CurrentDomain.BaseDirectory) + from version in io.GetVersion() + select version).ToEff(l => l); + }) + .Run(SAPRfcRuntime.Default); + + Console.WriteLine("Library Version: " + libVersion); + var connectionEffect = new ConnectionBuilder(settings) .ConfigureRuntime(c=>c.WithLogger(new SimpleConsoleLogger())) .BuildIO();