All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.finra.herd.service.impl.UploadDownloadServiceImpl Maven / Gradle / Ivy

Go to download

This project contains the business service code. This is a classic service tier where business logic is defined along with it's associated transaction management configuration.

There is a newer version: 0.160.0
Show newest version
/*
* Copyright 2015 herd contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.finra.herd.service.impl;

import java.util.Date;
import java.util.UUID;

import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.actions.S3Actions;
import com.amazonaws.services.securitytoken.model.Credentials;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import org.finra.herd.core.HerdDateUtils;
import org.finra.herd.core.helper.ConfigurationHelper;
import org.finra.herd.dao.S3Dao;
import org.finra.herd.dao.StsDao;
import org.finra.herd.dao.config.DaoSpringModuleConfig;
import org.finra.herd.dao.helper.AwsHelper;
import org.finra.herd.dao.helper.JsonHelper;
import org.finra.herd.model.ObjectNotFoundException;
import org.finra.herd.model.annotation.NamespacePermission;
import org.finra.herd.model.annotation.PublishNotificationMessages;
import org.finra.herd.model.api.xml.BusinessObjectData;
import org.finra.herd.model.api.xml.BusinessObjectDataCreateRequest;
import org.finra.herd.model.api.xml.BusinessObjectDataKey;
import org.finra.herd.model.api.xml.BusinessObjectDataStorageFileKey;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionKey;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionSampleDataFileKey;
import org.finra.herd.model.api.xml.BusinessObjectFormat;
import org.finra.herd.model.api.xml.DownloadBusinessObjectDataStorageFileSingleInitiationRequest;
import org.finra.herd.model.api.xml.DownloadBusinessObjectDataStorageFileSingleInitiationResponse;
import org.finra.herd.model.api.xml.DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationRequest;
import org.finra.herd.model.api.xml.DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationResponse;
import org.finra.herd.model.api.xml.DownloadSingleInitiationResponse;
import org.finra.herd.model.api.xml.NamespacePermissionEnum;
import org.finra.herd.model.api.xml.UploadBusinessObjectDefinitionSampleDataFileInitiationRequest;
import org.finra.herd.model.api.xml.UploadBusinessObjectDefinitionSampleDataFileInitiationResponse;
import org.finra.herd.model.api.xml.UploadSingleCredentialExtensionResponse;
import org.finra.herd.model.api.xml.UploadSingleInitiationRequest;
import org.finra.herd.model.api.xml.UploadSingleInitiationResponse;
import org.finra.herd.model.dto.CompleteUploadSingleParamsDto;
import org.finra.herd.model.dto.ConfigurationValue;
import org.finra.herd.model.dto.S3FileTransferRequestParamsDto;
import org.finra.herd.model.jpa.BusinessObjectDataEntity;
import org.finra.herd.model.jpa.BusinessObjectDataStatusEntity;
import org.finra.herd.model.jpa.BusinessObjectDefinitionEntity;
import org.finra.herd.model.jpa.BusinessObjectDefinitionSampleDataFileEntity;
import org.finra.herd.model.jpa.BusinessObjectFormatEntity;
import org.finra.herd.model.jpa.StorageEntity;
import org.finra.herd.model.jpa.StorageFileEntity;
import org.finra.herd.model.jpa.StorageUnitEntity;
import org.finra.herd.service.UploadDownloadHelperService;
import org.finra.herd.service.UploadDownloadService;
import org.finra.herd.service.helper.AlternateKeyHelper;
import org.finra.herd.service.helper.AttributeHelper;
import org.finra.herd.service.helper.AwsPolicyBuilder;
import org.finra.herd.service.helper.BusinessObjectDataDaoHelper;
import org.finra.herd.service.helper.BusinessObjectDataHelper;
import org.finra.herd.service.helper.BusinessObjectDefinitionDaoHelper;
import org.finra.herd.service.helper.BusinessObjectDefinitionHelper;
import org.finra.herd.service.helper.BusinessObjectFormatDaoHelper;
import org.finra.herd.service.helper.BusinessObjectFormatHelper;
import org.finra.herd.service.helper.KmsActions;
import org.finra.herd.service.helper.S3KeyPrefixHelper;
import org.finra.herd.service.helper.StorageDaoHelper;
import org.finra.herd.service.helper.StorageFileDaoHelper;
import org.finra.herd.service.helper.StorageHelper;
import org.finra.herd.service.helper.StorageUnitDaoHelper;
import org.finra.herd.service.helper.UploadDownloadHelper;

/**
 * The upload download service implementation.
 */
@Service
@Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME)
public class UploadDownloadServiceImpl implements UploadDownloadService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(UploadDownloadServiceImpl.class);

    @Autowired
    private AlternateKeyHelper alternateKeyHelper;

    @Autowired
    private AttributeHelper attributeHelper;

    @Autowired
    private AwsHelper awsHelper;

    @Autowired
    private BusinessObjectDataDaoHelper businessObjectDataDaoHelper;

    @Autowired
    private BusinessObjectDataHelper businessObjectDataHelper;

    @Autowired
    private BusinessObjectFormatDaoHelper businessObjectFormatDaoHelper;

    @Autowired
    private BusinessObjectFormatHelper businessObjectFormatHelper;

    @Autowired
    private BusinessObjectDefinitionDaoHelper businessObjectDefinitionDaoHelper;

    @Autowired
    private BusinessObjectDefinitionHelper businessObjectDefinitionHelper;

    @Autowired
    private ConfigurationHelper configurationHelper;

    @Autowired
    private JsonHelper jsonHelper;

    @Autowired
    private S3KeyPrefixHelper s3KeyPrefixHelper;

    @Autowired
    private S3Dao s3Dao;

    @Autowired
    private StorageDaoHelper storageDaoHelper;

    @Autowired
    private StorageFileDaoHelper storageFileDaoHelper;

    @Autowired
    private StorageHelper storageHelper;

    @Autowired
    private StorageUnitDaoHelper storageUnitDaoHelper;

    @Autowired
    private StsDao stsDao;

    @Autowired
    private UploadDownloadHelper uploadDownloadHelper;

    @Autowired
    private UploadDownloadHelperService uploadDownloadHelperService;

    @PublishNotificationMessages
    @NamespacePermission(fields = {"#uploadSingleInitiationRequest?.sourceBusinessObjectFormatKey?.namespace",
        "#uploadSingleInitiationRequest?.targetBusinessObjectFormatKey?.namespace"}, permissions = NamespacePermissionEnum.WRITE)
    @Override
    public UploadSingleInitiationResponse initiateUploadSingle(UploadSingleInitiationRequest uploadSingleInitiationRequest)
    {
        // Validate and trim the request parameters.
        validateUploadSingleInitiationRequest(uploadSingleInitiationRequest);

        // Get the business object format for the specified parameters and make sure it exists.
        BusinessObjectFormatEntity sourceBusinessObjectFormatEntity =
            businessObjectFormatDaoHelper.getBusinessObjectFormatEntity(uploadSingleInitiationRequest.getSourceBusinessObjectFormatKey());

        // Get the target business object format entity for the specified parameters and make sure it exists.
        BusinessObjectFormatEntity targetBusinessObjectFormatEntity =
            businessObjectFormatDaoHelper.getBusinessObjectFormatEntity(uploadSingleInitiationRequest.getTargetBusinessObjectFormatKey());

        // Get the S3 managed "loading dock" storage entity and make sure it exists.
        StorageEntity sourceStorageEntity = storageDaoHelper.getStorageEntity(StorageEntity.MANAGED_LOADING_DOCK_STORAGE);

        // Get S3 bucket name for the storage. Please note that since those values are required we pass a "true" flag.
        String s3BucketName = storageHelper.getStorageBucketName(sourceStorageEntity);

        // Get the S3 managed "external" storage entity and make sure it exists.
        String targetStorageName;
        if (uploadSingleInitiationRequest.getTargetStorageName() != null)
        {
            targetStorageName = uploadSingleInitiationRequest.getTargetStorageName();
        }
        else
        {
            targetStorageName = configurationHelper.getProperty(ConfigurationValue.S3_EXTERNAL_STORAGE_NAME_DEFAULT);
        }
        StorageEntity targetStorageEntity = storageDaoHelper.getStorageEntity(targetStorageName);

        assertTargetStorageEntityValid(targetStorageEntity);

        // Generate a random UUID value.
        String uuid = UUID.randomUUID().toString();

        // Create business object data key with partition value set to the generated UUID.
        BusinessObjectDataKey businessObjectDataKey = new BusinessObjectDataKey(uploadSingleInitiationRequest.getSourceBusinessObjectFormatKey().getNamespace(),
            uploadSingleInitiationRequest.getSourceBusinessObjectFormatKey().getBusinessObjectDefinitionName(),
            uploadSingleInitiationRequest.getSourceBusinessObjectFormatKey().getBusinessObjectFormatUsage(),
            uploadSingleInitiationRequest.getSourceBusinessObjectFormatKey().getBusinessObjectFormatFileType(),
            uploadSingleInitiationRequest.getSourceBusinessObjectFormatKey().getBusinessObjectFormatVersion(), uuid, null,
            BusinessObjectDataEntity.BUSINESS_OBJECT_DATA_INITIAL_VERSION);

        // Get a file upload specific S3 key prefix for the source storage based on the generated UUID.
        String sourceStorageDirectoryPath = s3KeyPrefixHelper.buildS3KeyPrefix(sourceStorageEntity, sourceBusinessObjectFormatEntity, businessObjectDataKey);
        String sourceStorageFilePath = String.format("%s/%s", sourceStorageDirectoryPath, uploadSingleInitiationRequest.getFile().getFileName());

        // Create a business object data create request.
        BusinessObjectDataCreateRequest sourceBusinessObjectDataCreateRequest = businessObjectDataHelper
            .createBusinessObjectDataCreateRequest(sourceBusinessObjectFormatEntity, uuid, BusinessObjectDataStatusEntity.UPLOADING,
                uploadSingleInitiationRequest.getBusinessObjectDataAttributes(), sourceStorageEntity, sourceStorageDirectoryPath, sourceStorageFilePath,
                uploadSingleInitiationRequest.getFile().getFileSizeBytes(), null);

        // Create a new business object data instance. Set the flag to false, since for the file upload service the file size value is optional.
        BusinessObjectData sourceBusinessObjectData = businessObjectDataDaoHelper.createBusinessObjectData(sourceBusinessObjectDataCreateRequest, false);

        // Get a file upload specific S3 key prefix for the target storage based on the generated UUID.
        String targetStorageDirectoryPath = s3KeyPrefixHelper.buildS3KeyPrefix(targetStorageEntity, targetBusinessObjectFormatEntity, businessObjectDataKey);
        String targetStorageFilePath = String.format("%s/%s", targetStorageDirectoryPath, uploadSingleInitiationRequest.getFile().getFileName());

        uploadDownloadHelperService.assertS3ObjectKeyDoesNotExist(storageHelper.getStorageBucketName(targetStorageEntity), targetStorageFilePath);

        // Create a target business object data based on the source business object data and target business object format.
        BusinessObjectDataCreateRequest targetBusinessObjectDataCreateRequest = businessObjectDataHelper
            .createBusinessObjectDataCreateRequest(targetBusinessObjectFormatEntity, uuid, BusinessObjectDataStatusEntity.UPLOADING,
                uploadSingleInitiationRequest.getBusinessObjectDataAttributes(), targetStorageEntity, targetStorageDirectoryPath, targetStorageFilePath,
                uploadSingleInitiationRequest.getFile().getFileSizeBytes(), null);

        // Create a target business object data instance. Set the flag to false, since for the file upload service the file size value is optional.
        BusinessObjectData targetBusinessObjectData = businessObjectDataDaoHelper.createBusinessObjectData(targetBusinessObjectDataCreateRequest, false);

        // Get decrypted AWS ARN of the role that is required to provide access to S3_MANAGED_LOADING_DOCK storage.
        String awsRoleArn = getStorageUploadRoleArn(sourceStorageEntity);

        // Get expiration interval for the pre-signed URL to be generated.
        Integer awsRoleDurationSeconds = getStorageUploadSessionDuration(sourceStorageEntity);

        String awsKmsKeyId = storageHelper.getStorageKmsKeyId(sourceStorageEntity);

        // Get the temporary security credentials to access S3_MANAGED_STORAGE.
        Credentials assumedSessionCredentials = stsDao
            .getTemporarySecurityCredentials(awsHelper.getAwsParamsDto(), String.valueOf(sourceBusinessObjectData.getId()), awsRoleArn, awsRoleDurationSeconds,
                createUploaderPolicy(s3BucketName, sourceStorageFilePath, awsKmsKeyId));

        // Create the response.
        UploadSingleInitiationResponse response = new UploadSingleInitiationResponse();
        response.setSourceBusinessObjectData(sourceBusinessObjectData);
        response.setTargetBusinessObjectData(targetBusinessObjectData);
        response.setFile(uploadSingleInitiationRequest.getFile());
        response.setUuid(uuid);
        response.setAwsAccessKey(assumedSessionCredentials.getAccessKeyId());
        response.setAwsSecretKey(assumedSessionCredentials.getSecretAccessKey());
        response.setAwsSessionToken(assumedSessionCredentials.getSessionToken());
        response.setAwsSessionExpirationTime(HerdDateUtils.getXMLGregorianCalendarValue(assumedSessionCredentials.getExpiration()));
        response.setAwsKmsKeyId(awsKmsKeyId);
        response.setTargetStorageName(targetStorageName);

        return response;
    }

    /**
     * Asserts that the given target storage entity has valid attributes.
     *
     * @param targetStorageEntity Target storage entity.
     */
    private void assertTargetStorageEntityValid(StorageEntity targetStorageEntity)
    {
        try
        {
            // Assert that the target storage has a bucket name
            storageHelper.getStorageBucketName(targetStorageEntity);
        }
        catch (IllegalStateException e)
        {
            throw new IllegalArgumentException(e.getMessage(), e);
        }

        try
        {
            // Assert that the target storage has a KMS key ID
            storageHelper.getStorageKmsKeyId(targetStorageEntity);
        }
        catch (IllegalStateException e)
        {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    /**
     * Creates a restricted policy JSON string which only allows PutObject to the given bucket name and object key, and allows GenerateDataKey and Decrypt for
     * the given key ID. The Decrypt is required for multipart upload with KMS encryption.
     *
     * @param s3BucketName - The S3 bucket name to restrict uploads to
     * @param s3Key - The S3 object key to restrict the uploads to
     * @param awsKmsKeyId - The KMS key ID to allow access
     *
     * @return the policy JSON string
     */
    @SuppressWarnings("PMD.CloseResource") // These are not SQL statements so they don't need to be closed.
    private Policy createUploaderPolicy(String s3BucketName, String s3Key, String awsKmsKeyId)
    {
        return new AwsPolicyBuilder().withS3(s3BucketName, s3Key, S3Actions.PutObject).withKms(awsKmsKeyId, KmsActions.GENERATE_DATA_KEY, KmsActions.DECRYPT)
            .build();
    }

    @SuppressWarnings("PMD.CloseResource") // These are not SQL statements so they don't need to be closed.
    private Policy createUploaderPolicyNoKmsKey(String s3BucketName, String s3Key)
    {
        return new AwsPolicyBuilder().withS3(s3BucketName, s3Key, S3Actions.PutObject).build();
    }

    /**
     * Creates a restricted policy JSON string which only allows GetObject to the given bucket name and object key, and allows Decrypt for the given key ID.
     *
     * @param s3BucketName - The S3 bucket name to restrict uploads to
     * @param s3Key - The S3 object key to restrict the uploads to
     * @param awsKmsKeyId - The KMS key ID to allow access
     *
     * @return the policy JSON string
     */
    @SuppressWarnings("PMD.CloseResource") // These are not SQL statements so they don't need to be closed.
    private Policy createDownloaderPolicy(String s3BucketName, String s3Key, String awsKmsKeyId)
    {
        return new AwsPolicyBuilder().withS3(s3BucketName, s3Key, S3Actions.GetObject).withKms(awsKmsKeyId, KmsActions.DECRYPT).build();
    }

    /**
     * Creates a restricted policy JSON string which only allows GetObject to the given bucket name and object key, and allows Decrypt for the given key ID.
     *
     * @param s3BucketName - The S3 bucket name to restrict uploads to
     * @param s3Key - The S3 object key to restrict the uploads to
     *
     * @return the policy JSON string
     */
    @SuppressWarnings("PMD.CloseResource") // These are not SQL statements so they don't need to be closed.
    private Policy createDownloaderPolicy(String s3BucketName, String s3Key)
    {
        return new AwsPolicyBuilder().withS3(s3BucketName, s3Key, S3Actions.GetObject).build();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public CompleteUploadSingleMessageResult performCompleteUploadSingleMessage(String objectKey)
    {
        return performCompleteUploadSingleMessageImpl(objectKey);
    }

    /**
     * Performs the completion of upload single file. Runs in new transaction and logs the error if an error occurs.
     *
     * @param objectKey the object key.
     *
     * @return CompleteUploadSingleMessageResult
     */
    protected CompleteUploadSingleMessageResult performCompleteUploadSingleMessageImpl(String objectKey)
    {
        // Create an instance of complete upload single parameters DTO.
        CompleteUploadSingleParamsDto completeUploadSingleParamsDto = new CompleteUploadSingleParamsDto();

        // Prepare for the file move.
        // TODO: To make our implementation Mockito friendly, we need to re-write the upload download
        // TODO: helper methods to make them return the updated DTO back instead of being void methods.
        uploadDownloadHelperService.prepareForFileMove(objectKey, completeUploadSingleParamsDto);

        // Create an instance of the result message for complete upload single operation.
        CompleteUploadSingleMessageResult completeUploadSingleMessageResult = new CompleteUploadSingleMessageResult();
        completeUploadSingleMessageResult.setSourceBusinessObjectDataKey(completeUploadSingleParamsDto.getSourceBusinessObjectDataKey());
        completeUploadSingleMessageResult.setSourceOldBusinessObjectDataStatus(completeUploadSingleParamsDto.getSourceOldStatus());
        completeUploadSingleMessageResult.setSourceNewBusinessObjectDataStatus(completeUploadSingleParamsDto.getSourceNewStatus());
        completeUploadSingleMessageResult.setTargetBusinessObjectDataKey(completeUploadSingleParamsDto.getTargetBusinessObjectDataKey());
        completeUploadSingleMessageResult.setTargetOldBusinessObjectDataStatus(completeUploadSingleParamsDto.getTargetOldStatus());
        completeUploadSingleMessageResult.setTargetNewBusinessObjectDataStatus(completeUploadSingleParamsDto.getTargetNewStatus());

        // If both source and target business object data have RE-ENCRYPTING status, continue the processing.
        if (BusinessObjectDataStatusEntity.RE_ENCRYPTING.equals(completeUploadSingleParamsDto.getSourceNewStatus()) &&
            BusinessObjectDataStatusEntity.RE_ENCRYPTING.equals(completeUploadSingleParamsDto.getTargetNewStatus()))
        {
            // Move the S3 file from the source to the target bucket.
            uploadDownloadHelperService.performFileMove(completeUploadSingleParamsDto);

            // Execute the steps required to complete the processing of the complete upload single message.
            uploadDownloadHelperService.executeFileMoveAfterSteps(completeUploadSingleParamsDto);

            // Delete the source file from the S3
            uploadDownloadHelperService.deleteSourceFileFromS3(completeUploadSingleParamsDto);

            // Update the result message.
            completeUploadSingleMessageResult.setSourceNewBusinessObjectDataStatus(completeUploadSingleParamsDto.getSourceNewStatus());
            completeUploadSingleMessageResult.setTargetNewBusinessObjectDataStatus(completeUploadSingleParamsDto.getTargetNewStatus());
        }

        // Log the result of the complete upload single operation.
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("completeUploadSingleMessageResult={}", jsonHelper.objectToJson(completeUploadSingleMessageResult));
        }

        return completeUploadSingleMessageResult;
    }

    /*
     * The result of completeUploadSingleMessage, contains the source and target business object data key, old and new status.
     */
    public static class CompleteUploadSingleMessageResult
    {
        private BusinessObjectDataKey sourceBusinessObjectDataKey;

        private String sourceOldBusinessObjectDataStatus;

        private String sourceNewBusinessObjectDataStatus;

        private BusinessObjectDataKey targetBusinessObjectDataKey;

        private String targetOldBusinessObjectDataStatus;

        private String targetNewBusinessObjectDataStatus;

        public BusinessObjectDataKey getSourceBusinessObjectDataKey()
        {
            return sourceBusinessObjectDataKey;
        }

        public void setSourceBusinessObjectDataKey(BusinessObjectDataKey sourceBusinessObjectDataKey)
        {
            this.sourceBusinessObjectDataKey = sourceBusinessObjectDataKey;
        }

        public String getSourceOldBusinessObjectDataStatus()
        {
            return sourceOldBusinessObjectDataStatus;
        }

        public void setSourceOldBusinessObjectDataStatus(String sourceOldBusinessObjectDataStatus)
        {
            this.sourceOldBusinessObjectDataStatus = sourceOldBusinessObjectDataStatus;
        }

        public String getSourceNewBusinessObjectDataStatus()
        {
            return sourceNewBusinessObjectDataStatus;
        }

        public void setSourceNewBusinessObjectDataStatus(String sourceNewBusinessObjectDataStatus)
        {
            this.sourceNewBusinessObjectDataStatus = sourceNewBusinessObjectDataStatus;
        }

        public BusinessObjectDataKey getTargetBusinessObjectDataKey()
        {
            return targetBusinessObjectDataKey;
        }

        public void setTargetBusinessObjectDataKey(BusinessObjectDataKey targetBusinessObjectDataKey)
        {
            this.targetBusinessObjectDataKey = targetBusinessObjectDataKey;
        }

        public String getTargetOldBusinessObjectDataStatus()
        {
            return targetOldBusinessObjectDataStatus;
        }

        public void setTargetOldBusinessObjectDataStatus(String targetOldBusinessObjectDataStatus)
        {
            this.targetOldBusinessObjectDataStatus = targetOldBusinessObjectDataStatus;
        }

        public String getTargetNewBusinessObjectDataStatus()
        {
            return targetNewBusinessObjectDataStatus;
        }

        public void setTargetNewBusinessObjectDataStatus(String targetNewBusinessObjectDataStatus)
        {
            this.targetNewBusinessObjectDataStatus = targetNewBusinessObjectDataStatus;
        }
    }

    /**
     * Validates the upload single initiation request. This method also trims the request parameters.
     *
     * @param request the upload single initiation request
     */
    private void validateUploadSingleInitiationRequest(UploadSingleInitiationRequest request)
    {
        Assert.notNull(request, "An upload single initiation request must be specified.");

        // Validate and trim the source business object format key.
        businessObjectFormatHelper.validateBusinessObjectFormatKey(request.getSourceBusinessObjectFormatKey());

        // Validate and trim the target business object format key.
        businessObjectFormatHelper.validateBusinessObjectFormatKey(request.getTargetBusinessObjectFormatKey());

        // Validate and trim the attributes.
        attributeHelper.validateAttributes(request.getBusinessObjectDataAttributes());

        // Validate and trim the file information.
        Assert.notNull(request.getFile(), "File information must be specified.");
        Assert.hasText(request.getFile().getFileName(), "A file name must be specified.");
        request.getFile().setFileName(request.getFile().getFileName().trim());

        String targetStorageName = request.getTargetStorageName();
        if (targetStorageName != null)
        {
            request.setTargetStorageName(targetStorageName.trim());
        }
    }

    @NamespacePermission(fields = "#namespace", permissions = NamespacePermissionEnum.READ)
    @Override
    public DownloadSingleInitiationResponse initiateDownloadSingle(String namespace, String businessObjectDefinitionName, String businessObjectFormatUsage,
        String businessObjectFormatFileType, Integer businessObjectFormatVersion, String partitionValue, Integer businessObjectDataVersion)
    {
        // Create the business object data key.
        BusinessObjectDataKey businessObjectDataKey =
            new BusinessObjectDataKey(namespace, businessObjectDefinitionName, businessObjectFormatUsage, businessObjectFormatFileType,
                businessObjectFormatVersion, partitionValue, null, businessObjectDataVersion);

        // Validate the parameters
        businessObjectDataHelper.validateBusinessObjectDataKey(businessObjectDataKey, true, true);

        // Retrieve the persisted business object data
        BusinessObjectDataEntity businessObjectDataEntity = businessObjectDataDaoHelper.getBusinessObjectDataEntity(businessObjectDataKey);

        // Make sure the status of the business object data is VALID
        businessObjectDataHelper.assertBusinessObjectDataStatusEquals(BusinessObjectDataStatusEntity.VALID, businessObjectDataEntity);

        // Get the external storage registered against this data
        // Validate that the storage unit exists
        StorageUnitEntity storageUnitEntity = IterableUtils.get(businessObjectDataEntity.getStorageUnits(), 0);

        // Validate that the storage unit contains only 1 file
        assertHasOneStorageFile(storageUnitEntity);

        String s3BucketName = storageHelper.getStorageBucketName(storageUnitEntity.getStorage());
        String s3ObjectKey = IterableUtils.get(storageUnitEntity.getStorageFiles(), 0).getPath();

        // Get the temporary credentials
        Credentials downloaderCredentials =
            getExternalDownloaderCredentials(storageUnitEntity.getStorage(), String.valueOf(businessObjectDataEntity.getId()), s3ObjectKey);

        // Generate a pre-signed URL
        Date expiration = downloaderCredentials.getExpiration();
        S3FileTransferRequestParamsDto s3BucketAccessParams = storageHelper.getS3BucketAccessParams(storageUnitEntity.getStorage());
        String presignedUrl = s3Dao.generateGetObjectPresignedUrl(s3BucketName, s3ObjectKey, expiration, s3BucketAccessParams);

        // Construct and return the response
        DownloadSingleInitiationResponse response = new DownloadSingleInitiationResponse();
        response.setBusinessObjectData(businessObjectDataHelper.createBusinessObjectDataFromEntity(businessObjectDataEntity));
        response.setAwsAccessKey(downloaderCredentials.getAccessKeyId());
        response.setAwsSecretKey(downloaderCredentials.getSecretAccessKey());
        response.setAwsSessionToken(downloaderCredentials.getSessionToken());
        response.setAwsSessionExpirationTime(HerdDateUtils.getXMLGregorianCalendarValue(expiration));
        response.setPreSignedUrl(presignedUrl);
        return response;
    }

    @NamespacePermission(fields = "#namespace", permissions = NamespacePermissionEnum.WRITE)
    @Override
    public UploadSingleCredentialExtensionResponse extendUploadSingleCredentials(String namespace, String businessObjectDefinitionName,
        String businessObjectFormatUsage, String businessObjectFormatFileType, Integer businessObjectFormatVersion, String partitionValue,
        Integer businessObjectDataVersion)
    {
        // Create the business object data key.
        BusinessObjectDataKey businessObjectDataKey =
            new BusinessObjectDataKey(namespace, businessObjectDefinitionName, businessObjectFormatUsage, businessObjectFormatFileType,
                businessObjectFormatVersion, partitionValue, null, businessObjectDataVersion);

        // Validate and trim the business object data key.
        businessObjectDataHelper.validateBusinessObjectDataKey(businessObjectDataKey, true, true);

        // Get the business object data for the key.
        BusinessObjectDataEntity businessObjectDataEntity = businessObjectDataDaoHelper.getBusinessObjectDataEntity(businessObjectDataKey);

        // Ensure the status of the business object data is "uploading" in order to extend credentials.
        if (!(businessObjectDataEntity.getStatus().getCode().equals(BusinessObjectDataStatusEntity.UPLOADING)))
        {
            throw new IllegalArgumentException(String.format(String
                .format("Business object data {%s} has a status of \"%s\" and must be \"%s\" to extend " + "credentials.",
                    businessObjectDataHelper.businessObjectDataKeyToString(businessObjectDataKey), businessObjectDataEntity.getStatus().getCode(),
                    BusinessObjectDataStatusEntity.UPLOADING)));
        }

        // Get the S3 managed "loading dock" storage entity and make sure it exists.
        StorageEntity storageEntity = storageDaoHelper.getStorageEntity(StorageEntity.MANAGED_LOADING_DOCK_STORAGE);

        String s3BucketName = storageHelper.getStorageBucketName(storageEntity);

        // Get the storage unit entity for this business object data in the S3 managed "loading dock" storage and make sure it exists.
        StorageUnitEntity storageUnitEntity = storageUnitDaoHelper.getStorageUnitEntity(StorageEntity.MANAGED_LOADING_DOCK_STORAGE, businessObjectDataEntity);

        // Validate that the storage unit contains exactly one storage file.
        assertHasOneStorageFile(storageUnitEntity);

        // Get the storage file entity.
        StorageFileEntity storageFileEntity = IterableUtils.get(storageUnitEntity.getStorageFiles(), 0);

        // Get the storage file path.
        String storageFilePath = storageFileEntity.getPath();

        String awsRoleArn = getStorageUploadRoleArn(storageEntity);

        Integer awsRoleDurationSeconds = getStorageUploadSessionDuration(storageEntity);

        String awsKmsKeyId = storageHelper.getStorageKmsKeyId(storageEntity);

        // Get the temporary security credentials to access S3_MANAGED_STORAGE.
        Credentials assumedSessionCredentials = stsDao
            .getTemporarySecurityCredentials(awsHelper.getAwsParamsDto(), String.valueOf(businessObjectDataEntity.getId()), awsRoleArn, awsRoleDurationSeconds,
                createUploaderPolicy(s3BucketName, storageFilePath, awsKmsKeyId));

        // Create the response.
        UploadSingleCredentialExtensionResponse response = new UploadSingleCredentialExtensionResponse();
        response.setAwsAccessKey(assumedSessionCredentials.getAccessKeyId());
        response.setAwsSecretKey(assumedSessionCredentials.getSecretAccessKey());
        response.setAwsSessionToken(assumedSessionCredentials.getSessionToken());
        response.setAwsSessionExpirationTime(HerdDateUtils.getXMLGregorianCalendarValue(assumedSessionCredentials.getExpiration()));

        return response;
    }

    /**
     * Asserts that the given storage unit entity contains exactly one storage file.
     *
     * @param storageUnitEntity - storage unit to check
     *
     * @throws IllegalArgumentException when the number of storage files is not 1
     */
    private void assertHasOneStorageFile(StorageUnitEntity storageUnitEntity)
    {
        Assert.isTrue(storageUnitEntity.getStorageFiles().size() == 1, String
            .format("Found %d registered storage files when expecting one in \"%s\" storage for the business object data {%s}.",
                storageUnitEntity.getStorageFiles().size(), storageUnitEntity.getStorage().getName(),
                businessObjectDataHelper.businessObjectDataEntityAltKeyToString(storageUnitEntity.getBusinessObjectData())));
    }

    /**
     * Gets a temporary session token that is only good for downloading the specified object key from the given bucket for a limited amount of time.
     *
     * @param storageEntity The storage entity of the external storage
     * @param sessionName the session name to use for the temporary credentials.
     * @param s3ObjectKey the S3 object key of the path to the data in the bucket.
     *
     * @return {@link Credentials} temporary session token
     */
    private Credentials getExternalDownloaderCredentials(StorageEntity storageEntity, String sessionName, String s3ObjectKey)
    {
        return stsDao.getTemporarySecurityCredentials(awsHelper.getAwsParamsDto(), sessionName, getStorageDownloadRoleArn(storageEntity),
            configurationHelper.getProperty(ConfigurationValue.AWS_S3_DEFAULT_DOWNLOAD_SESSION_DURATION_SECS, Integer.class),
            createDownloaderPolicy(storageHelper.getStorageBucketName(storageEntity), s3ObjectKey, storageHelper.getStorageKmsKeyId(storageEntity)));
    }

    /**
     * Gets a temporary session token that is only good for downloading the specified object key from the given bucket for a limited amount of time.
     *
     * @param storageEntity The storage entity of the external storage.
     * @param sessionName The session name to use for the temporary credentials.
     * @param s3ObjectKey The S3 object key of the path to the data in the bucket.
     *
     * @return {@link Credentials} temporary session token
     */
    private Credentials getDownloaderCredentialsNoKmsKey(StorageEntity storageEntity, String sessionName, String s3ObjectKey)
    {
        return stsDao.getTemporarySecurityCredentials(awsHelper.getAwsParamsDto(), sessionName, getStorageDownloadRoleArn(storageEntity),
            configurationHelper.getProperty(ConfigurationValue.AWS_S3_DEFAULT_DOWNLOAD_SESSION_DURATION_SECS, Integer.class),
            createDownloaderPolicy(storageHelper.getStorageBucketName(storageEntity), s3ObjectKey));
    }

    /**
     * Gets a temporary session token that is only good for downloading the specified object key from the given bucket for a limited amount of time.
     *
     * @param storageEntity The storage entity of the external storage.
     * @param sessionName The session name to use for the temporary credentials.
     * @param awsPolicyBuilder The AWS policy builder.
     *
     * @return {@link Credentials} temporary session token
     */
    private Credentials getDownloaderCredentials(StorageEntity storageEntity, String sessionName, AwsPolicyBuilder awsPolicyBuilder)
    {
        return stsDao.getTemporarySecurityCredentials(awsHelper.getAwsParamsDto(), sessionName, getStorageDownloadRoleArn(storageEntity),
            configurationHelper.getProperty(ConfigurationValue.AWS_S3_DEFAULT_DOWNLOAD_SESSION_DURATION_SECS, Integer.class), awsPolicyBuilder.build());
    }

    /**
     * Gets the storage's upload session duration in seconds. Defaults to the configured default value if not defined.
     *
     * @param storageEntity The storage entity
     *
     * @return Upload session duration in seconds
     */
    private Integer getStorageUploadSessionDuration(StorageEntity storageEntity)
    {
        return storageHelper
            .getStorageAttributeIntegerValueByName(configurationHelper.getProperty(ConfigurationValue.S3_ATTRIBUTE_NAME_UPLOAD_SESSION_DURATION_SECS),
                storageEntity, configurationHelper.getProperty(ConfigurationValue.AWS_S3_DEFAULT_UPLOAD_SESSION_DURATION_SECS, Integer.class));
    }

    /**
     * Gets the storage's upload role ARN. Throws if not defined.
     *
     * @param storageEntity The storage entity
     *
     * @return Upload role ARN
     */
    private String getStorageUploadRoleArn(StorageEntity storageEntity)
    {
        return storageHelper
            .getStorageAttributeValueByName(configurationHelper.getProperty(ConfigurationValue.S3_ATTRIBUTE_NAME_UPLOAD_ROLE_ARN), storageEntity, true);
    }

    /**
     * Gets the storage's download role ARN. Throws if not defined.
     *
     * @param storageEntity The storage entity
     *
     * @return Download role ARN
     */
    private String getStorageDownloadRoleArn(StorageEntity storageEntity)
    {
        return storageHelper
            .getStorageAttributeValueByName(configurationHelper.getProperty(ConfigurationValue.S3_ATTRIBUTE_NAME_DOWNLOAD_ROLE_ARN), storageEntity, true);
    }

    @Override
    public DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationResponse initiateDownloadSingleSampleFile(
        DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationRequest request)
    {
        // Validate and trim the request parameters.
        validateDownloadBusinessObjectDefinitionSampleDataFileSingleInitiationRequest(request);

        // Get the business object definition sample data file key.
        BusinessObjectDefinitionSampleDataFileKey businessObjectDefinitionSampleDataFileKey = request.getBusinessObjectDefinitionSampleDataFileKey();

        // Get the business object definition key.
        BusinessObjectDefinitionKey businessObjectDefinitionKey = new BusinessObjectDefinitionKey(businessObjectDefinitionSampleDataFileKey.getNamespace(),
            businessObjectDefinitionSampleDataFileKey.getBusinessObjectDefinitionName());

        // Get the business object definition entity and ensure it exists.
        BusinessObjectDefinitionEntity businessObjectDefinitionEntity =
            businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey);

        // Get the sample data file exists for the business object definition and ensure it exists.
        BusinessObjectDefinitionSampleDataFileEntity businessObjectDefinitionSampleDataFileEntity =
            getBusinessObjectDefinitionSampleDataFileEntity(businessObjectDefinitionEntity, businessObjectDefinitionSampleDataFileKey);

        // Retrieve the storage related information.
        StorageEntity storageEntity = businessObjectDefinitionSampleDataFileEntity.getStorage();
        String s3BucketName = storageHelper.getStorageBucketName(storageEntity);
        String s3ObjectKey = businessObjectDefinitionSampleDataFileKey.getDirectoryPath() + businessObjectDefinitionSampleDataFileKey.getFileName();

        String sessionID = UUID.randomUUID().toString();
        // Get the temporary credentials.
        Credentials downloaderCredentials = getDownloaderCredentialsNoKmsKey(storageEntity, sessionID, s3ObjectKey);

        // Generate a pre-signed URL.
        Date expiration = downloaderCredentials.getExpiration();
        S3FileTransferRequestParamsDto s3BucketAccessParams = storageHelper.getS3BucketAccessParams(storageEntity);
        String presignedUrl = s3Dao.generateGetObjectPresignedUrl(s3BucketName, s3ObjectKey, expiration, s3BucketAccessParams);

        // Create the download business object definition sample data file single initiation response.
        DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationResponse response =
            new DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationResponse();
        response.setBusinessObjectDefinitionSampleDataFileKey(
            new BusinessObjectDefinitionSampleDataFileKey(businessObjectDefinitionEntity.getNamespace().getCode(), businessObjectDefinitionEntity.getName(),
                businessObjectDefinitionSampleDataFileEntity.getDirectoryPath(), businessObjectDefinitionSampleDataFileEntity.getFileName()));
        response.setAwsS3BucketName(s3BucketName);
        response.setAwsAccessKey(downloaderCredentials.getAccessKeyId());
        response.setAwsSecretKey(downloaderCredentials.getSecretAccessKey());
        response.setAwsSessionToken(downloaderCredentials.getSessionToken());
        response.setAwsSessionExpirationTime(HerdDateUtils.getXMLGregorianCalendarValue(expiration));
        response.setPreSignedUrl(presignedUrl);

        // Return the response.
        return response;
    }

    /**
     * Validates the download business object definition sample data file single initiation request.
     *
     * @param request the download business object definition sample data file single initiation request request
     */
    private void validateDownloadBusinessObjectDefinitionSampleDataFileSingleInitiationRequest(
        DownloadBusinessObjectDefinitionSampleDataFileSingleInitiationRequest request)
    {
        Assert.notNull(request, "A download business object definition sample data file single initiation request must be specified.");
        validateBusinessObjectDefinitionSampleDataFileKey(request.getBusinessObjectDefinitionSampleDataFileKey());
    }

    /**
     * Validates a business object definition sample data file key. This method also trims the key parameters.
     *
     * @param key the business object definition sample data file key
     */
    private void validateBusinessObjectDefinitionSampleDataFileKey(BusinessObjectDefinitionSampleDataFileKey key)
    {
        Assert.notNull(key, "A business object definition sample data file key must be specified.");
        key.setNamespace(alternateKeyHelper.validateStringParameter("namespace", key.getNamespace()));
        key.setBusinessObjectDefinitionName(
            alternateKeyHelper.validateStringParameter("business object definition name", key.getBusinessObjectDefinitionName()));
        Assert.hasText(key.getDirectoryPath(), "A directory path must be specified.");
        key.setDirectoryPath(key.getDirectoryPath().trim());
        Assert.hasText(key.getFileName(), "A file name must be specified.");
        key.setFileName(key.getFileName().trim());
    }

    /**
     * Gets a business object definition sample data file entity per specified parameters.
     *
     * @param businessObjectDefinitionEntity the business object definition entity
     * @param businessObjectDefinitionSampleDataFileKey the business object definition sample data file key
     *
     * @return the business object definition sample data file entity
     */
    private BusinessObjectDefinitionSampleDataFileEntity getBusinessObjectDefinitionSampleDataFileEntity(
        BusinessObjectDefinitionEntity businessObjectDefinitionEntity, BusinessObjectDefinitionSampleDataFileKey businessObjectDefinitionSampleDataFileKey)
    {
        BusinessObjectDefinitionSampleDataFileEntity businessObjectDefinitionSampleDataFileEntity = null;

        for (BusinessObjectDefinitionSampleDataFileEntity sampleDataFileEntity : businessObjectDefinitionEntity.getSampleDataFiles())
        {
            if (sampleDataFileEntity.getDirectoryPath().equals(businessObjectDefinitionSampleDataFileKey.getDirectoryPath()) &&
                sampleDataFileEntity.getFileName().equals(businessObjectDefinitionSampleDataFileKey.getFileName()))
            {
                businessObjectDefinitionSampleDataFileEntity = sampleDataFileEntity;
                break;
            }
        }

        if (businessObjectDefinitionSampleDataFileEntity == null)
        {
            throw new ObjectNotFoundException(String.format(
                "Business object definition with name \"%s\" and namespace \"%s\" does not have the specified sample file registered with file name \"%s\" in" +
                    " directory path \"%s\"", businessObjectDefinitionSampleDataFileKey.getBusinessObjectDefinitionName(),
                businessObjectDefinitionSampleDataFileKey.getNamespace(), businessObjectDefinitionSampleDataFileKey.getFileName(),
                businessObjectDefinitionSampleDataFileKey.getDirectoryPath()));
        }

        return businessObjectDefinitionSampleDataFileEntity;
    }

    /**
     * Validate upload business object definition sample file request
     *
     * @param request the sample data file upload initiation request
     */
    private void validateUploadBusinessObjectDefinitionSampleDataFileInitiationRequest(UploadBusinessObjectDefinitionSampleDataFileInitiationRequest request)
    {
        Assert.notNull(request, "An upload initiation request must be specified.");
        BusinessObjectDefinitionKey businessObjectDefinitionKey = request.getBusinessObjectDefinitionKey();
        // Perform validation and trim.
        businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey);
    }

    @NamespacePermission(fields = "#request.businessObjectDefinitionKey.namespace", permissions = {NamespacePermissionEnum.WRITE_DESCRIPTIVE_CONTENT,
        NamespacePermissionEnum.WRITE})
    @Override
    public UploadBusinessObjectDefinitionSampleDataFileInitiationResponse initiateUploadSampleFile(
        UploadBusinessObjectDefinitionSampleDataFileInitiationRequest request)
    {
        validateUploadBusinessObjectDefinitionSampleDataFileInitiationRequest(request);

        BusinessObjectDefinitionKey businessObjectDefinitionKey = request.getBusinessObjectDefinitionKey();
        // Get the business object definition entity and ensure it exists.
        BusinessObjectDefinitionEntity businessObjectDefinitionEntity =
            businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey);
        businessObjectDefinitionKey.setNamespace(businessObjectDefinitionEntity.getNamespace().getCode());
        businessObjectDefinitionKey.setBusinessObjectDefinitionName(businessObjectDefinitionEntity.getName());

        UploadBusinessObjectDefinitionSampleDataFileInitiationResponse response = new UploadBusinessObjectDefinitionSampleDataFileInitiationResponse();
        StorageEntity storageEntity = storageDaoHelper.getStorageEntity(StorageEntity.SAMPLE_DATA_FILE_STORAGE);

        String s3BucketName = storageHelper.getStorageBucketName(storageEntity);
        String s3EndPoint = storageHelper.getS3BucketAccessParams(storageEntity).getS3Endpoint();
        String awsRoleArn = getStorageUploadRoleArn(storageEntity);
        String sessionID = UUID.randomUUID().toString();
        String s3KeyPrefix = s3KeyPrefixHelper.buildS3KeyPrefix(storageEntity, businessObjectDefinitionKey);
        s3KeyPrefix = StringUtils.appendIfMissing(s3KeyPrefix, "/");
        //need to add star for aws authorization
        String s3Path = s3KeyPrefix + "*";

        Integer awsRoleDurationSeconds = getStorageUploadSessionDuration(storageEntity);

        Credentials assumedSessionCredentials = stsDao
            .getTemporarySecurityCredentials(awsHelper.getAwsParamsDto(), sessionID, awsRoleArn, awsRoleDurationSeconds,
                createUploaderPolicyNoKmsKey(s3BucketName, s3Path));

        response.setAwsAccessKey(assumedSessionCredentials.getAccessKeyId());
        response.setAwsSecretKey(assumedSessionCredentials.getSecretAccessKey());
        response.setAwsSessionToken(assumedSessionCredentials.getSessionToken());
        response.setAwsSessionExpirationTime(HerdDateUtils.getXMLGregorianCalendarValue(assumedSessionCredentials.getExpiration()));

        response.setAwsS3BucketName(s3BucketName);
        response.setBusinessObjectDefinitionKey(businessObjectDefinitionKey);
        response.setS3Endpoint(s3EndPoint);
        response.setS3KeyPrefix(s3KeyPrefix);
        return response;
    }

    @NamespacePermission(fields = "#downloadBusinessObjectDataStorageFileSingleInitiationRequest.businessObjectDataStorageFileKey.namespace",
        permissions = NamespacePermissionEnum.READ)
    @Override
    public DownloadBusinessObjectDataStorageFileSingleInitiationResponse initiateDownloadSingleBusinessObjectDataStorageFile(
        DownloadBusinessObjectDataStorageFileSingleInitiationRequest downloadBusinessObjectDataStorageFileSingleInitiationRequest)
    {
        // Validate and trim the request.
        uploadDownloadHelper
            .validateAndTrimDownloadBusinessObjectDataStorageFileSingleInitiationRequest(downloadBusinessObjectDataStorageFileSingleInitiationRequest);

        // Get the business object data storage file key.
        BusinessObjectDataStorageFileKey businessObjectDataStorageFileKey =
            downloadBusinessObjectDataStorageFileSingleInitiationRequest.getBusinessObjectDataStorageFileKey();

        // Retrieve and validate that the business object data exists.
        BusinessObjectDataKey businessObjectDataKey = getBusinessObjectDataKeyFromBusinessObjectDataStorageFileKey(businessObjectDataStorageFileKey);
        BusinessObjectDataEntity businessObjectDataEntity = businessObjectDataDaoHelper.getBusinessObjectDataEntity(businessObjectDataKey);

        // Retrieve and validate that the storage unit exists
        StorageUnitEntity storageUnitEntity =
            storageUnitDaoHelper.getStorageUnitEntity(businessObjectDataStorageFileKey.getStorageName(), businessObjectDataEntity);

        // Get the storage file entity and ensure it exists.
        StorageFileEntity storageFileEntity =
            storageFileDaoHelper.getStorageFileEntity(storageUnitEntity, businessObjectDataStorageFileKey.getFilePath(), businessObjectDataKey);

        // Get S3 bucket access parameters.
        StorageEntity storageEntity = storageFileEntity.getStorageUnit().getStorage();

        // Retrieve the storage related information.
        String s3BucketName = storageHelper.getStorageBucketName(storageEntity);
        String s3ObjectKey = businessObjectDataStorageFileKey.getFilePath();

        // Create an AWS policy builder.
        AwsPolicyBuilder awsPolicyBuilder = new AwsPolicyBuilder().withS3(s3BucketName, s3ObjectKey, S3Actions.GetObject);

        // Get the storage kms key id.
        String storageKmsKeyId = storageHelper
            .getStorageAttributeValueByName(configurationHelper.getProperty(ConfigurationValue.S3_ATTRIBUTE_NAME_KMS_KEY_ID), storageEntity, false, true);

        /*
         * Only add KMS policies if the storage specifies a KMS ID
         */
        if (storageKmsKeyId != null)
        {
            awsPolicyBuilder.withKms(storageKmsKeyId.trim(), KmsActions.DECRYPT);
        }

        // Create a sessionId.
        String sessionId = UUID.randomUUID().toString();

        // Get the temporary credentials.
        Credentials downloaderCredentials = getDownloaderCredentials(storageEntity, sessionId, awsPolicyBuilder);

        // Generate a pre-signed URL.
        Date expiration = downloaderCredentials.getExpiration();
        S3FileTransferRequestParamsDto s3BucketAccessParams = storageHelper.getS3BucketAccessParams(storageEntity);
        String preSignedUrl = s3Dao.generateGetObjectPresignedUrl(s3BucketName, s3ObjectKey, expiration, s3BucketAccessParams);

        // Convert the business object format entity to the business object format model object
        BusinessObjectFormat businessObjectFormat =
            businessObjectFormatHelper.createBusinessObjectFormatFromEntity(businessObjectDataEntity.getBusinessObjectFormat());

        // Create a business object data storage file key for the download business object data storage file single initiation response.
        BusinessObjectDataStorageFileKey businessObjectDataStorageFileKeyForResponse =
            new BusinessObjectDataStorageFileKey(businessObjectFormat.getNamespace(), businessObjectFormat.getBusinessObjectDefinitionName(),
                businessObjectFormat.getBusinessObjectFormatUsage(), businessObjectFormat.getBusinessObjectFormatFileType(),
                businessObjectFormat.getBusinessObjectFormatVersion(), businessObjectDataEntity.getPartitionValue(),
                businessObjectDataHelper.getSubPartitionValues(businessObjectDataEntity), businessObjectDataEntity.getVersion(),
                storageUnitEntity.getStorageName(), storageFileEntity.getPath());

        // Create the download business object data storage file single initiation response.
        DownloadBusinessObjectDataStorageFileSingleInitiationResponse downloadBusinessObjectDataStorageFileSingleInitiationResponse =
            new DownloadBusinessObjectDataStorageFileSingleInitiationResponse();
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setBusinessObjectDataStorageFileKey(businessObjectDataStorageFileKeyForResponse);
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setAwsS3BucketName(s3BucketName);
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setAwsAccessKey(downloaderCredentials.getAccessKeyId());
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setAwsSecretKey(downloaderCredentials.getSecretAccessKey());
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setAwsSessionToken(downloaderCredentials.getSessionToken());
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setAwsSessionExpirationTime(HerdDateUtils.getXMLGregorianCalendarValue(expiration));
        downloadBusinessObjectDataStorageFileSingleInitiationResponse.setPreSignedUrl(preSignedUrl);

        // Return the download business object data storage file single initiation response.
        return downloadBusinessObjectDataStorageFileSingleInitiationResponse;
    }

    /**
     * Gets a business object data key from a specified business object data storage file key.
     *
     * @param businessObjectDataStorageFileKey the business object data storage file key
     *
     * @return the business object data key
     */
    private BusinessObjectDataKey getBusinessObjectDataKeyFromBusinessObjectDataStorageFileKey(
        BusinessObjectDataStorageFileKey businessObjectDataStorageFileKey)
    {
        return new BusinessObjectDataKey(businessObjectDataStorageFileKey.getNamespace(), businessObjectDataStorageFileKey.getBusinessObjectDefinitionName(),
            businessObjectDataStorageFileKey.getBusinessObjectFormatUsage(), businessObjectDataStorageFileKey.getBusinessObjectFormatFileType(),
            businessObjectDataStorageFileKey.getBusinessObjectFormatVersion(), businessObjectDataStorageFileKey.getPartitionValue(),
            businessObjectDataStorageFileKey.getSubPartitionValues(), businessObjectDataStorageFileKey.getBusinessObjectDataVersion());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy