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

HttpTransferCommand

using Relativity.Transfer.Http.Issues; using Relativity.Transfer.Http.Paths; using Relativity.Transfer.Http.Resources; using Relativity.Transfer.Paths; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace Relativity.Transfer.Http { internal sealed class HttpTransferCommand : TransferPathCommandBase { private const string LogPrefix = "HTTP Transfer Command"; private readonly HttpClientConfiguration configuration; private readonly ISoapFileTransferService fileTransferService; private readonly HttpTransferIssueBuilderFactory issueBuilderFactory; public HttpTransferCommand(ITransferLog log, ITransferRequest request, ITransferJobService jobService, IFileSystemService fileSystemService, HttpClientConfiguration configuration, ISoapFileTransferService fileTransferService) : base(log, request, jobService, fileSystemService, configuration) { if (fileTransferService == null) throw new ArgumentNullException("fileTransferService"); if (configuration == null) throw new ArgumentNullException("configuration"); this.fileTransferService = fileTransferService; this.configuration = configuration; issueBuilderFactory = new HttpTransferIssueBuilderFactory(this.configuration); } [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "There are numerous exceptions and exception types to check for improved error handling.")] [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Reviewed OK.")] protected override TransferPathResult OnExecute(TransferPath path, CancellationToken token) { if (!(path == (TransferPath)null)) { TransferPathResult transferPathResult = new TransferPathResult { Path = path, Status = TransferPathStatus.Started, StartTime = new DateTime?(DateTime.Now) }; try { if (!token.IsCancellationRequested) { LargeFileProgress progress = (base.LargeFileProgressProvider != null) ? new LargeFileProgress(OnLargeFileProgress, base.LargeFileProgressRateSeconds) : null; TaskAwaiter<TransferPathResult> awaiter; switch (base.Request.Direction) { case TransferDirection.Download: { Task<TransferPathResult> task2 = fileTransferService.DownloadAsync(path, token, progress); task2.Wait(token); awaiter = task2.GetAwaiter(); transferPathResult = awaiter.GetResult(); break; } case TransferDirection.Upload: { Task<TransferPathResult> task = fileTransferService.UploadAsync(path, token, progress); task.Wait(token); awaiter = task.GetAwaiter(); transferPathResult = awaiter.GetResult(); break; } } if (transferPathResult.Status == TransferPathStatus.Successful || transferPathResult.Status == TransferPathStatus.Skipped) base.JobService.Statistics.TotalTransferredFiles++; base.JobService.Statistics.TotalTransferredBytes += transferPathResult.BytesTransferred; PublishTransferStatistics(false); if (token.IsCancellationRequested) { transferPathResult.Status = TransferPathStatus.Canceled; transferPathResult.EndTime = DateTime.Now; } return transferPathResult; } transferPathResult.Status = TransferPathStatus.Canceled; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } catch (ArgumentException ex) { base.Log.LogError(ex, "The transfer path contains one or more invalid data.", Array.Empty<object>()); IssueAttributes attribute = IssueAttributes.Error | IssueAttributes.File | IssueAttributes.InvalidCharacters; PublishTransferIssue(path, attribute, ex); throw new TransferException(ex.Message, ex, true); } catch (UnauthorizedAccessException exception) { return HandleUnauthorizedAccessException(path, exception, transferPathResult, configuration.MaxJobRetryAttempts); } catch (IOException ex2) { base.Log.LogError(ex2, $"""{FormatPathInfo(path)}""", Array.Empty<object>()); IssueAttributes attribute2 = IssueAttributes.File | IssueAttributes.Io | IssueAttributes.StorageReadWrite | GetWarningErrorAttribute(); PublishTransferIssue(path, attribute2, ex2); throw new TransferException(ex2.Message, ex2, false); } catch (OperationCanceledException) { HandleCancel(transferPathResult); return transferPathResult; } catch (AggregateException ex4) { IssueAttributes issueAttributes = HandleAggregateException(ex4, path); if (issueAttributes.HasFlag(IssueAttributes.Error)) base.Log.LogError(ex4, $"""{FormatPathInfo(path)}", Array.Empty<object>()); else if (issueAttributes.HasFlag(IssueAttributes.Warning)) { base.Log.LogWarning(ex4, $"""{FormatPathInfo(path)}""", Array.Empty<object>()); } if (!issueAttributes.HasFlag(IssueAttributes.FileNotFound)) { if (!base.FilePermissionErrorsRetry || !issueAttributes.HasFlag(IssueAttributes.ReadWritePermissions)) { HttpPathStatusResolver httpPathStatusResolver = new HttpPathStatusResolver(new PathStatusResolver(configuration)); using (IEnumerator<Exception> enumerator = ex4.Flatten().InnerExceptions.GetEnumerator()) { if (enumerator.MoveNext()) { Exception current = enumerator.Current; TransferPathStatus transferPathStatus = httpPathStatusResolver.Resolve(current); if (transferPathStatus == TransferPathStatus.Fatal) throw new TransferException(HttpErrorCodes.GetErrorMessage(current), current, true); transferPathResult.Status = transferPathStatus; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } } throw new TransferException(ex4.Message, ex4, false); } transferPathResult.Status = TransferPathStatus.PermissionsError; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } transferPathResult.Status = TransferPathStatus.FileNotFound; transferPathResult.EndTime = DateTime.Now; return transferPathResult; } catch (Exception ex5) { base.Log.LogError(ex5, $"""{FormatPathInfo(path)}", Array.Empty<object>()); IssueAttributes attribute3 = GetWarningErrorAttribute() | IssueAttributes.File; PublishTransferIssue(path, attribute3, ex5); throw new TransferException(ex5.Message, ex5, false); } } throw new ArgumentNullException("path"); } [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Reviewed OK.")] protected override void OnPreExecute(CancellationToken token) { if (!token.IsCancellationRequested) try { base.Log.LogInformation("{0} - Attempting to authenticate with Relativity.", "HTTP Transfer Command"); fileTransferService.Login(); base.Log.LogInformation("{0} - Successfully authenticated with Relativity.", "HTTP Transfer Command"); } catch (AggregateException ex) { base.Log.LogError(ex, HttpStrings.AuthenticationError, Array.Empty<object>()); HandleAggregateException(ex, null); } catch (Exception exception) { base.Log.LogError(exception, HttpStrings.AuthenticationError, Array.Empty<object>()); PublishTransferIssue(null, IssueAttributes.Authentication | IssueAttributes.Warning, exception); } } private IssueAttributes HandleAggregateException(AggregateException aggregateException, TransferPath path) { if (aggregateException == null) throw new ArgumentNullException("aggregateException"); IssueAttributes issueAttributes = (path != (TransferPath)null) ? IssueAttributes.File : IssueAttributes.Job; foreach (Exception innerException in aggregateException.Flatten().InnerExceptions) { IssueAttributes issueAttributesFromException = GetIssueAttributesFromException(path, innerException); issueAttributes |= issueAttributesFromException; PublishTransferIssue(path, issueAttributesFromException, innerException); } return issueAttributes; } private IssueAttributes GetIssueAttributesFromException(TransferPath path, Exception exception) { IssueAttributes issueAttributes = (path != (TransferPath)null) ? IssueAttributes.File : IssueAttributes.Job; if (!(exception.GetType() == typeof(UnauthorizedAccessException))) { if (!(exception.GetType() == typeof(ArgumentException))) { if (!(exception.GetType() == typeof(FileNotFoundException))) { if (!(exception.GetType() == typeof(DirectoryNotFoundException))) { if (!(exception.GetType() == typeof(HttpRequestException))) { if (!(exception.GetType() == typeof(OverflowException))) return issueAttributes | GetWarningErrorAttribute(); return issueAttributes | IssueAttributes.Error; } issueAttributes |= (IssueAttributes.File | IssueAttributes.Io); if (exception.Message.IndexOf("409", StringComparison.OrdinalIgnoreCase) <= 0) return issueAttributes | GetWarningErrorAttribute(); return issueAttributes | (IssueAttributes.FileNotFound | (base.FileNotFoundErrorsDisabled ? IssueAttributes.Warning : GetWarningErrorAttribute())); } return issueAttributes | (IssueAttributes.DirectoryNotFound | IssueAttributes.File | IssueAttributes.Io | GetWarningErrorAttribute()); } return issueAttributes | (IssueAttributes.File | IssueAttributes.FileNotFound | IssueAttributes.Io | (base.FileNotFoundErrorsDisabled ? IssueAttributes.Warning : GetWarningErrorAttribute())); } return issueAttributes | (IssueAttributes.Error | IssueAttributes.File | IssueAttributes.InvalidCharacters); } return issueAttributes | (IssueAttributes.File | IssueAttributes.ReadWritePermissions | (base.FilePermissionErrorsRetry ? GetWarningErrorAttribute() : IssueAttributes.Error)); } private void PublishTransferIssue(TransferPath path, IssueAttributes attribute, Exception exception) { ITransferIssue issue = issueBuilderFactory.Create().CreateFromException(path, exception).WithAttributes(attribute) .WithMaxRetryAttempts(configuration.MaxJobRetryAttempts) .WithRetryAttempt(base.JobService.Statistics.RetryAttempt) .Build(); RegisterIssue(issue); } private string FormatPathInfo(TransferPath path) { return $"""{base.Request.Direction.ToString()}""{path.SourcePath}""{path.TargetFileName ?? string.Empty}""{path.TargetPath}"""; } } }