RelativityDistributedFacade
This is a facade for the Relativity.Distributed service.
using Relativity.DataExchange.Io;
using Relativity.Logging;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net;
namespace Relativity.DataExchange.Service.RelativityDistributed
{
internal class RelativityDistributedFacade : IRelativityDistributedFacade
{
private const string AccessDeniedMarker = "KCURAACCESSDENIEDMARKER";
private readonly ILog logger;
private readonly IAppSettings settings;
private readonly IFile fileHelper;
private readonly string downloadUrl;
private readonly NetworkCredential credentials;
private readonly CookieContainer ;
private readonly Func<string> authenticationTokenProvider;
public RelativityDistributedFacade(ILog logger, IAppSettings settings, IFile fileHelper, string relativityDistributedUrl, NetworkCredential credentials, CookieContainer cookieContainer, Func<string> authenticationTokenProvider)
{
this.logger = logger;
this.settings = settings;
this.fileHelper = fileHelper;
downloadUrl = UrlHelper.GetBaseUrlAndCombine(this.settings.WebApiServiceUrl, relativityDistributedUrl);
this.cookieContainer = cookieContainer;
this.credentials = credentials;
this.authenticationTokenProvider = authenticationTokenProvider;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method uses result instead of exceptions.")]
public FileDownloadResponse DownloadFile(FileDownloadRequest request)
{
logger.LogInformation("Attempting to download an error file using Relativity.Distributed. Request: {@request}", new object[1] {
request
});
try {
HttpWebRequest httpWebRequest = CreateDownloadRequest(request);
long num = 0;
using (WebResponse webResponse = httpWebRequest.GetResponse()) {
num = Math.Max(webResponse.ContentLength, 0);
using (Stream stream = webResponse.GetResponseStream())
using (Stream destination = GetDestinationFileStream(request.DestinationFilePath, true))
stream?.CopyTo(destination, settings.WebBasedFileDownloadChunkSize);
}
long fileSize = fileHelper.GetFileSize(request.DestinationFilePath);
if (num != fileSize && num > 0) {
logger.LogError("Error retrieving data from distributed server; expecting " + num.ToString() + " bytes and received " + fileSize.ToString(), Array.Empty<object>());
return new FileDownloadResponse(RelativityDistributedErrorType.DataCorrupted);
}
return new FileDownloadResponse();
} catch (WebException ex) {
HttpWebResponse httpWebResponse = ex.Response as HttpWebResponse;
if (httpWebResponse != null) {
switch (httpWebResponse.StatusCode) {
case HttpStatusCode.Forbidden:
if (httpWebResponse.StatusDescription.ToUpperInvariant() == "KCURAACCESSDENIEDMARKER")
return new FileDownloadResponse(RelativityDistributedErrorType.Authentication, ex);
break;
case HttpStatusCode.Conflict:
return new FileDownloadResponse(RelativityDistributedErrorType.NotFound, ex);
case HttpStatusCode.InternalServerError:
return new FileDownloadResponse(RelativityDistributedErrorType.InternalServerError, ex);
}
}
LogError(ex, request);
return new FileDownloadResponse(RelativityDistributedErrorType.Unknown, ex);
} catch (Exception exception) {
LogError(exception, request);
return new FileDownloadResponse(RelativityDistributedErrorType.Unknown, exception);
}
}
private HttpWebRequest CreateDownloadRequest(FileDownloadRequest request)
{
HttpWebRequest obj = (HttpWebRequest)WebRequest.Create(BuildDownloadUrl(request));
obj.Credentials = credentials;
obj.CookieContainer = cookieContainer;
obj.UnsafeAuthenticatedConnectionSharing = true;
return obj;
}
private string BuildDownloadUrl(FileDownloadRequest request)
{
string text = downloadUrl.TrimEnd(new char[1] {
'/'
}) + "/";
string text2 = text + "Download.aspx?ArtifactID=-1&GUID=" + request.RemoteFileGuid + "&AppID=" + request.WorkspaceId;
string text3 = authenticationTokenProvider();
if (!string.IsNullOrEmpty(text3))
text2 = text2 + "&AuthenticationToken=" + text3;
return text2;
}
private Stream GetDestinationFileStream(string destinationFilePath, bool shouldRetry = true)
{
try {
return fileHelper.Create(destinationFilePath);
} catch (Exception ex) {
logger.LogError(ex, "An error occured when creating destination file: {destinationFilePath}. Will retry: {shouldRetry}", new object[2] {
destinationFilePath,
shouldRetry
});
if (!shouldRetry)
throw;
return GetDestinationFileStream(destinationFilePath, false);
}
}
private void LogError(Exception exception, FileDownloadRequest request)
{
logger.LogError(exception, "An error occured when downloading the error file. Request: {@request}", new object[1] {
request
});
}
}
}