<PackageReference Include="Relativity.Transfer.Client" Version="7.2.26" />

WebApiService

using Polly; using Polly.Retry; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; namespace Relativity.Transfer { internal class WebApiService : IDisposable { private bool initialized; private bool disposed; public RelativityConnectionInfo ConnectionInfo { get; } public int MaxRetryAttempts { get; set; } public double TimeoutSeconds { get; set; } protected ClientConfiguration Configuration { get; } protected ITransferLog Log { get; } protected FileIO ServiceInstance { get; set; } protected IUserManagerService UserManagerService { get; } public WebApiService(RelativityConnectionInfo connectionInfo, ClientConfiguration configuration, IUserManagerService userManagerService, ITransferLog log) : this(connectionInfo, configuration, userManagerService, log, configuration.MaxHttpRetryAttempts, configuration.HttpTimeoutSeconds) { } public WebApiService(RelativityConnectionInfo connectionInfo, ClientConfiguration configuration, IUserManagerService userManagerService, ITransferLog log, int maxRetryAttempts, double timeoutSeconds) { if (connectionInfo == null) throw new ArgumentNullException("connectionInfo"); if (configuration == null) throw new ArgumentNullException("configuration"); if (userManagerService == null) throw new ArgumentNullException("userManagerService"); if (log == null) throw new ArgumentNullException("log"); Configuration = configuration; ConnectionInfo = connectionInfo; UserManagerService = userManagerService; ServiceInstance = null; Log = log; initialized = false; MaxRetryAttempts = maxRetryAttempts; TimeoutSeconds = timeoutSeconds; } ~WebApiService() { Dispose(false); } public static Uri GetWebApiServiceUrl(RelativityConnectionInfo connectionInfo, ITransferLog log) { if (connectionInfo == null) throw new ArgumentNullException("connectionInfo"); if (!(connectionInfo.WebApiServiceUrl != (Uri)null)) { connectionInfo.WebApiServiceUrl = UrlHelper.Combine(connectionInfo.Host, "RelativityWebAPI"); log.LogWarning("The WebApiServiceUrl wasn't assigned. Manually creating the {Url} URL to prevent failure.", connectionInfo.WebApiServiceUrl); return connectionInfo.WebApiServiceUrl; } return connectionInfo.WebApiServiceUrl; } public static IHttpCredential GetWebApiHttpCredential(RelativityConnectionInfo connectionInfo) { if (connectionInfo == null) throw new ArgumentNullException("connectionInfo"); return connectionInfo.WebApiServiceCredential ?? connectionInfo.Credential; } public Task<string> GetBcpSharePathAsync(int workspaceId, CancellationToken token) { if (workspaceId < 1 && workspaceId != -1) throw new ArgumentOutOfRangeException("workspaceId"); Initialize(); RetryPolicy retryPolicy = Policy.Handle<Exception>().WaitAndRetryAsync(MaxRetryAttempts, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan span) { Log.LogError(exception, $"""{span}", Array.Empty<object>()); CheckLogin(exception); }); return retryPolicy.ExecuteAsync(delegate { Task<string> task = Task.Factory.FromAsync((Func<AsyncCallback, object, IAsyncResult>)((AsyncCallback callback, object stateObject) => ServiceInstance.BeginGetBcpSharePath(workspaceId, callback, stateObject)), (Func<IAsyncResult, string>)ServiceInstance.EndGetBcpSharePath, (object)null); task.Wait(token); return task; }, token); } public Task<BcpStorageReport> GetBcpShareStorageReportAsync(int workspaceId, CancellationToken token) { if (workspaceId < 1 && workspaceId != -1) throw new ArgumentOutOfRangeException("workspaceId"); Initialize(); RetryPolicy retryPolicy = Policy.Handle<Exception>().WaitAndRetryAsync(MaxRetryAttempts, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan span) { Log.LogError(exception, $"""{span}", Array.Empty<object>()); CheckLogin(exception); }); return retryPolicy.ExecuteAsync(async delegate { Dictionary<string, string> reportDict = (await Task.Factory.FromAsync((Func<AsyncCallback, object, IAsyncResult>)((AsyncCallback callback, object stateObject) => ServiceInstance.BeginGetBcpShareSpaceReport(workspaceId, callback, stateObject)), (Func<IAsyncResult, string[][]>)ServiceInstance.EndGetBcpShareSpaceReport, (object)null).ConfigureAwait(false)).ToDictionary((string[] line) => line[0], (string[] line) => line[1]); BcpStorageReport report = new BcpStorageReport(); if (reportDict.ContainsKey("Drive Name")) report.DriveName = reportDict["Drive Name"]; if (reportDict.ContainsKey("Free Space")) report.TotalAvailableBytes = TryGetStorageReportBytes(reportDict["Free Space"]); if (reportDict.ContainsKey("Used Space")) report.TotalUsedBytes = TryGetStorageReportBytes(reportDict["Used Space"]); if (reportDict.ContainsKey("Total Space")) report.TotalBytes = TryGetStorageReportBytes(reportDict["Total Space"]); return report; }, token); } public Task<bool> ValidateBcpShareAsync(int workspaceId, CancellationToken token) { if (workspaceId < 1 && workspaceId != -1) throw new ArgumentOutOfRangeException("workspaceId"); Initialize(); RetryPolicy retryPolicy = Policy.Handle<Exception>().WaitAndRetryAsync(MaxRetryAttempts, (int retryAttempt) => TimeSpan.FromSeconds(Math.Pow(2, (double)retryAttempt)), delegate(Exception exception, TimeSpan span) { Log.LogError(exception, $"""{span}", Array.Empty<object>()); CheckLogin(exception); }); return retryPolicy.ExecuteAsync(async (CancellationToken ct) => await Task.Factory.FromAsync((Func<AsyncCallback, object, IAsyncResult>)((AsyncCallback callback, object stateObject) => ServiceInstance.BeginValidateBcpShare(workspaceId, callback, stateObject)), (Func<IAsyncResult, bool>)ServiceInstance.EndValidateBcpShare, (object)null).ConfigureAwait(false), token); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected void CheckLogin(Exception exception) { List<string> source = new List<string> { exception.ToString(), exception.InnerException?.ToString() ?? string.Empty }; bool flag = source.Any((string x) => x.IndexOf("kcuraaccessdeniedmarker", StringComparison.OrdinalIgnoreCase) != -1); bool flag2 = source.Any((string x) => x.IndexOf("NeedToReLoginException", StringComparison.OrdinalIgnoreCase) != -1); if (flag) { Log.LogInformation("An access denied exception occurred and requesting a new distributed login token.", Array.Empty<object>()); UserManagerService.Login(); } else if (flag2) { Log.LogInformation(string.IsNullOrWhiteSpace(UserManagerService.DistributedToken) ? "The distributed login token is null or empty and requesting a distributed login token." : "The distributed login token has expired and requesting a new distributed login token.", Array.Empty<object>()); UserManagerService.Login(); } } protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing && ServiceInstance != null) ((Component)ServiceInstance).Dispose(); disposed = true; } } protected virtual void Initialize() { if (!initialized) { FileIO fileIO = new FileIO(); fileIO.set_Credentials(GetWebApiHttpCredential(ConnectionInfo).CreateCredentials()); fileIO.set_CookieContainer(Configuration.CookieContainer); fileIO.set_Timeout((int)TimeSpan.FromSeconds(TimeoutSeconds).TotalMilliseconds); fileIO.set_Url(UrlHelper.Combine(GetWebApiServiceUrl(ConnectionInfo, Log), "FileIO.asmx").ToString()); ServiceInstance = fileIO; ServicePointManager.SecurityProtocol = (SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12); initialized = true; } } private long TryGetStorageReportBytes(string value) { try { string value2 = value.Replace(" MB", string.Empty); double bytes = ByteSize.FromMegaBytes(Convert.ToDouble(value2)).Bytes; return Convert.ToInt64(bytes); } catch (Exception exception) { Log.LogError(exception, "Failed to convert the {BcpValue} BCP storage report value to a long data type.", value); return 0; } } } }