public FileTransferMethod GetFileTransferMethod(long submittedJobInfoId, AdaptorUser loggedUser) { log.Info("Getting file transfer method for submitted job info ID " + submittedJobInfoId + " with user " + loggedUser.GetLogIdentification()); SubmittedJobInfo jobInfo = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork).GetSubmittedJobInfoById(submittedJobInfoId, loggedUser); var certificateGenerator = new CertificateGenerator.CertificateGenerator(); certificateGenerator.GenerateKey(2048); string publicKey = certificateGenerator.DhiPublicKey(); string jobDir = FileSystemUtils.GetJobClusterDirectoryPath(jobInfo.Specification.FileTransferMethod.Cluster.LocalBasepath, jobInfo.Specification); var transferMethod = new FileTransferMethod { Protocol = jobInfo.Specification.FileTransferMethod.Protocol, ServerHostname = jobInfo.Specification.FileTransferMethod.ServerHostname, SharedBasePath = jobDir, Credentials = new AsymmetricKeyCredentials { Username = jobInfo.Specification.ClusterUser.Username, PrivateKey = certificateGenerator.DhiPrivateKey(), PublicKey = publicKey } }; SchedulerFactory.GetInstance(jobInfo.Specification.Cluster.SchedulerType).CreateScheduler(jobInfo.Specification.Cluster).AllowDirectFileTransferAccessForUserToJob(publicKey, jobInfo); return(transferMethod); }
public ClusterNodeUsage GetCurrentClusterNodeUsage(long clusterNodeId, AdaptorUser loggedUser) { ClusterNodeType nodeType = GetClusterNodeTypeById(clusterNodeId); return(SchedulerFactory.GetInstance(nodeType.Cluster.SchedulerType).CreateScheduler(nodeType.Cluster) .GetCurrentClusterNodeUsage(nodeType)); }
internal static AdaptorUser GetUserForSessionCode(string sessionCode, IUnitOfWork unitOfWork) { IUserAndLimitationManagementLogic authenticationLogic = LogicFactory.GetLogicFactory().CreateUserAndLimitationManagementLogic(unitOfWork); AdaptorUser loggedUser = authenticationLogic.GetUserForSessionCode(sessionCode); return(loggedUser); }
/// <summary> /// Get user for given <paramref name="sessionCode"/> and check if the user has <paramref name="requiredUserRole"/>. /// </summary> /// <param name="sessionCode">User session code.</param> /// <param name="unitOfWork">Unit of work.</param> /// <param name="requiredUserRole">Required user role.</param> /// <returns>AdaptorUser object if user has required user role.</returns> /// <exception cref="InsufficientRoleException">Is thrown if the user doesn't have <paramref name="requiredUserRole"/>.</exception> internal static AdaptorUser GetValidatedUserForSessionCode(string sessionCode, IUnitOfWork unitOfWork, UserRoleType requiredUserRole) { IUserAndLimitationManagementLogic authenticationLogic = LogicFactory.GetLogicFactory().CreateUserAndLimitationManagementLogic(unitOfWork); AdaptorUser loggedUser = authenticationLogic.GetUserForSessionCode(sessionCode); CheckUserRole(loggedUser, requiredUserRole); return(loggedUser); }
public static AdaptorUserExt ConvertIntToExt(this AdaptorUser user) { AdaptorUserExt convert = new AdaptorUserExt() { Id = user.Id, Username = user.Username }; return(convert); }
/// <summary> /// Check whether the user has any of the allowed roles to access given functionality. /// </summary> /// <param name="user">User account with roles.</param> /// <param name="requiredRole">Required user role.</param> /// <exception cref="InsufficientRoleException">is thrown when the user doesn't have any role specified by <see cref="allowedRoles"/></exception> internal static void CheckUserRole(AdaptorUser user, UserRoleType requiredUserRole) { bool hasRequiredRole = user.Roles.Any(userRole => (UserRoleType)userRole.Id == requiredUserRole); if (!hasRequiredRole) { using var unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork(); var requiredRoleModel = unitOfWork.AdaptorUserRoleRepository.GetById((long)requiredUserRole); throw InsufficientRoleException.CreateMissingRoleException(requiredRoleModel, user.Roles); } }
private double?GetResourceUsageForUser(AdaptorUser user, DateTime startTime, DateTime endTime, out ICollection <NodeTypeAggregatedUsage> nodeTypeAggregatedUsage) { double?userTotalUsage = 0; var selectedJobs = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork) .GetJobsForUser(user).Where(w => w.SubmitTime >= startTime && w.SubmitTime <= endTime) .ToList(); nodeTypeAggregatedUsage = new List <NodeTypeAggregatedUsage>(); if (selectedJobs is null) { return(default);
public virtual UserResourceUsageReport GetUserResourceUsageReport(long userId, DateTime startTime, DateTime endTime) { AdaptorUser user = unitOfWork.AdaptorUserRepository.GetById(userId); var userTotalUsage = GetResourceUsageForUser(user, startTime, endTime, out ICollection <NodeTypeAggregatedUsage> userNodeTypeAggregatedUsage); UserResourceUsageReport userReport = new UserResourceUsageReport { User = user, NodeTypeReport = userNodeTypeAggregatedUsage, TotalUsage = userTotalUsage, StartTime = startTime, EndTime = endTime }; return(userReport); }
public void DeleteJob(long submittedJobInfoId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IJobManagementLogic jobLogic = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork); jobLogic.DeleteJob(submittedJobInfoId, loggedUser); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); } }
public void EndFileTransfer(long submittedJobInfoId, FileTransferMethodExt usedTransferMethod, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IFileTransferLogic fileTransferLogic = LogicFactory.GetLogicFactory().CreateFileTransferLogic(unitOfWork); fileTransferLogic.EndFileTransfer(submittedJobInfoId, FileTransferConverts.ConvertFileTransferMethodExtToIn(usedTransferMethod), loggedUser); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); } }
public DataTransferMethodExt GetDataTransferMethod(string nodeIPAddress, int nodePort, long submittedTaskInfoId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IDataTransferLogic dataTransferLogic = LogicFactory.GetLogicFactory().CreateDataTransferLogic(unitOfWork); DataTransferMethod dataTransferMethod = dataTransferLogic.GetDataTransferMethod(nodeIPAddress, nodePort, submittedTaskInfoId, loggedUser); return(dataTransferMethod.ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(default);
public IEnumerable <AdaptorUserGroupExt> ListAdaptorUserGroups(string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Maintainer); IJobReportingLogic jobReportingLogic = LogicFactory.GetLogicFactory().CreateJobReportingLogic(unitOfWork); return(jobReportingLogic.ListAdaptorUserGroups().Select(s => s.ConvertIntToExt())); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public byte[] DownloadFileFromCluster(long submittedJobInfoId, string relativeFilePath, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IFileTransferLogic fileTransferLogic = LogicFactory.GetLogicFactory().CreateFileTransferLogic(unitOfWork); return(fileTransferLogic.DownloadFileFromCluster(submittedJobInfoId, relativeFilePath, loggedUser)); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public SubmittedJobInfoUsageReportExt GetResourceUsageReportForJob(long jobId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Reporter); IJobReportingLogic jobReportingLogic = LogicFactory.GetLogicFactory().CreateJobReportingLogic(unitOfWork); return(jobReportingLogic.GetResourceUsageReportForJob(jobId).ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public FileInformationExt[] ListChangedFilesForJob(long submittedJobInfoId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IFileTransferLogic fileTransferLogic = LogicFactory.GetLogicFactory().CreateFileTransferLogic(unitOfWork); ICollection <FileInformation> result = fileTransferLogic.ListChangedFilesForJob(submittedJobInfoId, loggedUser); return(result?.Select(s => s.ConvertIntToExt()).ToArray()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public FileTransferMethodExt GetFileTransferMethod(long submittedJobInfoId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IFileTransferLogic fileTransferLogic = LogicFactory.GetLogicFactory().CreateFileTransferLogic(unitOfWork); FileTransferMethod fileTransferMethod = fileTransferLogic.GetFileTransferMethod(submittedJobInfoId, loggedUser); return(fileTransferMethod.ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public string RemoveCommandTemplate(long commandTemplateId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Administrator); IManagementLogic managementLogic = LogicFactory.GetLogicFactory().CreateManagementLogic(unitOfWork); managementLogic.RemoveCommandTemplate(commandTemplateId); return($"CommandTemplate with id {commandTemplateId} has been removed."); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public SubmittedJobInfoExt SubmitJob(long createdJobInfoId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IJobManagementLogic jobLogic = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork); SubmittedJobInfo jobInfo = jobLogic.SubmitJob(createdJobInfoId, loggedUser); return(jobInfo.ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public IEnumerable <string> GetAllocatedNodesIPs(long submittedTaskInfoId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IJobManagementLogic jobLogic = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork); var nodesIPs = jobLogic.GetAllocatedNodesIPs(submittedTaskInfoId, loggedUser); return(nodesIPs.ToArray()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public SubmittedJobInfoExt[] ListJobsForCurrentUser(string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IJobManagementLogic jobLogic = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork); var jobInfos = jobLogic.GetJobsForUser(loggedUser); return(jobInfos.Select(s => s.ConvertIntToExt()).ToArray()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public ClusterNodeUsageExt GetCurrentClusterNodeUsage(long clusterNodeId, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Reporter); IClusterInformationLogic clusterLogic = LogicFactory.GetLogicFactory().CreateClusterInformationLogic(unitOfWork); ClusterNodeUsage nodeUsage = clusterLogic.GetCurrentClusterNodeUsage(clusterNodeId, loggedUser); return(nodeUsage.ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public ResourceUsageExt[] GetCurrentUsageAndLimitationsForCurrentUser(string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Reporter); IUserAndLimitationManagementLogic userLogic = LogicFactory.GetLogicFactory().CreateUserAndLimitationManagementLogic(unitOfWork); IList <ResourceUsage> usages = userLogic.GetCurrentUsageAndLimitationsForUser(loggedUser); return((from usage in usages select usage.ConvertIntToExt()).ToArray()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public SubmittedJobInfoExt CreateJob(JobSpecificationExt specification, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IJobManagementLogic jobLogic = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork); JobSpecification js = specification.ConvertExtToInt(); SubmittedJobInfo jobInfo = jobLogic.CreateJob(js, loggedUser, specification.IsExtraLong.Value); return(jobInfo.ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public JobFileContentExt[] DownloadPartsOfJobFilesFromCluster(long submittedJobInfoId, TaskFileOffsetExt[] taskFileOffsets, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IFileTransferLogic fileTransferLogic = LogicFactory.GetLogicFactory().CreateFileTransferLogic(unitOfWork); IList <JobFileContent> downloadedFileParts = fileTransferLogic.DownloadPartsOfJobFilesFromCluster( submittedJobInfoId, (from taskFileOffset in (new List <TaskFileOffsetExt>(taskFileOffsets).ToList()) select FileTransferConverts.ConvertTaskFileOffsetExtToIn(taskFileOffset)).ToArray(), loggedUser); return((from fileContent in downloadedFileParts select FileTransferConverts.ConvertJobFileContentToExt(fileContent)).ToArray()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public UserResourceUsageReportExt GetUserResourceUsageReport(long userId, DateTime startTime, DateTime endTime, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); if (loggedUser.Id != userId) { throw new NotAllowedException("Logged user is not allowed to request this report."); } IJobReportingLogic jobReportingLogic = LogicFactory.GetLogicFactory().CreateJobReportingLogic(unitOfWork); return(jobReportingLogic.GetUserResourceUsageReport(userId, startTime, endTime).ConvertIntToExt()); } } catch (Exception exc) { ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public CommandTemplateExt ModifyCommandTemplate(long commandTemplateId, string name, string description, string code, string executableFile, string preparationScript, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Administrator); IManagementLogic managementLogic = LogicFactory.GetLogicFactory().CreateManagementLogic(unitOfWork); CommandTemplate commandTemplate = managementLogic.ModifyCommandTemplate(commandTemplateId, name, description, code, executableFile, preparationScript); return(commandTemplate.ConvertIntToExt()); } } catch (Exception exc) { if (exc.Message.Contains("No such file or directory")) { ExceptionHandler.ThrowProperExternalException(new InputValidationException(exc.Message)); } ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public IEnumerable <string> GetCommandTemplateParametersName(long commandTemplateId, string userScriptPath, string sessionCode) { try { using (IUnitOfWork unitOfWork = UnitOfWorkFactory.GetUnitOfWorkFactory().CreateUnitOfWork()) { AdaptorUser loggedUser = UserAndLimitationManagementService.GetValidatedUserForSessionCode(sessionCode, unitOfWork, UserRoleType.Submitter); IClusterInformationLogic clusterLogic = LogicFactory.GetLogicFactory().CreateClusterInformationLogic(unitOfWork); return(clusterLogic.GetCommandTemplateParametersName(commandTemplateId, userScriptPath, loggedUser)); } } catch (Exception exc) { //TODO Should be rewrite! if (exc.Message.Contains("No such file or directory") || exc.Message.Contains("Is a directory")) { ExceptionHandler.ThrowProperExternalException(new InputValidationException(exc.Message)); } ExceptionHandler.ThrowProperExternalException(exc); return(null); } }
public IList <JobFileContent> DownloadPartsOfJobFilesFromCluster(long submittedJobInfoId, TaskFileOffset[] taskFileOffsets, AdaptorUser loggedUser) { log.Info("Getting part of job files from cluster for submitted job info ID " + submittedJobInfoId + " with user " + loggedUser.GetLogIdentification()); SubmittedJobInfo jobInfo = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork).GetSubmittedJobInfoById(submittedJobInfoId, loggedUser); IRexFileSystemManager fileManager = FileSystemFactory.GetInstance(jobInfo.Specification.FileTransferMethod.Protocol).CreateFileSystemManager(jobInfo.Specification.FileTransferMethod); IList <JobFileContent> result = new List <JobFileContent>(); foreach (SubmittedTaskInfo taskInfo in jobInfo.Tasks) { IList <TaskFileOffset> currentTaskFileOffsets = (from taskFileOffset in taskFileOffsets where taskFileOffset.SubmittedTaskInfoId == taskInfo.Id select taskFileOffset).ToList(); foreach (TaskFileOffset currentOffset in currentTaskFileOffsets) { ICollection <JobFileContent> contents = fileManager.DownloadPartOfJobFileFromCluster(taskInfo, currentOffset.FileType, currentOffset.Offset); if (contents != null) { foreach (JobFileContent content in contents) { result.Add(content); } } } } return(result); }
public void EndFileTransfer(long submittedJobInfoId, FileTransferMethod transferMethod, AdaptorUser loggedUser) { log.Info("Removing file transfer method for submitted job info ID " + submittedJobInfoId + " with user " + loggedUser.GetLogIdentification()); SubmittedJobInfo jobInfo = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork).GetSubmittedJobInfoById(submittedJobInfoId, loggedUser); AsymmetricKeyCredentials asymmetricKeyCredentials = transferMethod.Credentials as AsymmetricKeyCredentials; if (asymmetricKeyCredentials != null) { SchedulerFactory.GetInstance(jobInfo.Specification.Cluster.SchedulerType).CreateScheduler(jobInfo.Specification.Cluster). RemoveDirectFileTransferAccessForUserToJob(asymmetricKeyCredentials.PublicKey, jobInfo); } else { log.Error("Credentials of class " + transferMethod.Credentials.GetType().Name + " are not supported. Change the HaaSMiddleware.BusinessLogicTier.FileTransfer.FileTransferLogic.EndFileTransfer() method to add support for additional credential types."); throw new ArgumentException("Credentials of class " + transferMethod.Credentials.GetType().Name + " are not supported. Change the HaaSMiddleware.BusinessLogicTier.FileTransfer.FileTransferLogic.EndFileTransfer() method to add support for additional credential types."); } }
public byte[] DownloadFileFromCluster(long submittedJobInfoId, string relativeFilePath, AdaptorUser loggedUser) { SubmittedJobInfo jobInfo = LogicFactory.GetLogicFactory().CreateJobManagementLogic(unitOfWork).GetSubmittedJobInfoById(submittedJobInfoId, loggedUser); if (jobInfo.State < JobState.Submitted || jobInfo.State == JobState.WaitingForServiceAccount) { return(null); } IRexFileSystemManager fileManager = FileSystemFactory.GetInstance(jobInfo.Specification.FileTransferMethod.Protocol).CreateFileSystemManager(jobInfo.Specification.FileTransferMethod); try { return(fileManager.DownloadFileFromCluster(jobInfo, relativeFilePath)); } catch (SftpPathNotFoundException exception) { log.Warn($"{loggedUser.ToString()} is requesting not existing file '{relativeFilePath}'"); ExceptionHandler.ThrowProperExternalException(new InvalidRequestException(exception.Message)); } return(null); }