Class DefaultStorageService

java.lang.Object
com.broadleafcommerce.asset.service.DefaultStorageService
All Implemented Interfaces:
StorageService

public class DefaultStorageService extends Object implements StorageService
Author:
Chad Harchar (charchar), Samarth Dhruva (samarthd)
  • Field Details

    • FAILED_TO_STORE_FILE_ERROR_MESSAGE

      protected static final String FAILED_TO_STORE_FILE_ERROR_MESSAGE
      See Also:
    • FILE_UPLOAD_ERROR_MESSAGE

      protected static final String FILE_UPLOAD_ERROR_MESSAGE
      See Also:
    • MIME_TYPE_NOT_SUPPORTED_FMT

      public static final String MIME_TYPE_NOT_SUPPORTED_FMT
      See Also:
    • ONLY_ZIP_SUPPORTED

      public static final String ONLY_ZIP_SUPPORTED
      See Also:
    • ZIP_FILENAME_PATH_TRAVERSAL

      public static final String ZIP_FILENAME_PATH_TRAVERSAL
      See Also:
    • assetService

      protected final AssetService<Asset> assetService
    • folderService

      protected final FolderService<Folder> folderService
    • multipartConfigElement

      protected final jakarta.servlet.MultipartConfigElement multipartConfigElement
    • storageProvider

      protected final StorageProvider storageProvider
    • internalAssetProperties

      protected final InternalAssetProperties internalAssetProperties
    • typeFactory

      protected final com.broadleafcommerce.common.extension.TypeFactory typeFactory
    • imageOperationService

      protected final ImageOperationService imageOperationService
    • fileUploadStateService

      protected final FileUploadStateService<FileUploadState> fileUploadStateService
    • reference

      protected final com.broadleafcommerce.common.extension.data.DataRouteReference reference
    • assetStorageUtils

      protected AssetStorageUtils assetStorageUtils
  • Constructor Details

  • Method Details

    • uploadResource

      public Asset uploadResource(org.springframework.web.multipart.MultipartFile file, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg)
      Description copied from interface: StorageService
      Uploads a single file, creating an Asset for it (optionally using details specified in assetRequest if present).

      Validation includes:

      • File size is within the size limits of `spring.servlet.multipart.max-file-size`
      • File is of a supported mime type from `broadleaf.asset.storage.whitelisted-mime-type-formats`
      • File path and name does not already exist on a asset within the system
      Specified by:
      uploadResource in interface StorageService
      Parameters:
      file - the file to be uploaded to the system.
      assetRequest - (optional) asset from which to derive certain attributes when creating the final Asset for the file. Currently, Asset.tags and Asset.locale are used.
      contextInfo - context information around sandboxing and multitenant state
      optimizeImg - optimizes the image if true
      Returns:
      the created asset after the associated resource has been uploaded
    • validateFileAndCreateUrl

      protected String validateFileAndCreateUrl(org.springframework.web.multipart.MultipartFile file, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Validates the uploaded file and creates a URL for it.

      Intended to be overridden if there is some different validation or custom business logic required. For example, if an asset with the same URL already exists, the current implementation increments the file name with an increasing integer, like filename-1.txt. An alternate implementation may want to simply throw FileUploadBadRequestException.

      Parameters:
      file - the uploaded file
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      the created url
      Throws:
      org.springframework.web.multipart.MaxUploadSizeExceededException - if the file is too large
      FileUploadBadRequestException - if the mime type of the file is not supported
      IllegalArgumentException - if the filename is invalid
    • validateFileAndCreateUrl

      protected String validateFileAndCreateUrl(org.springframework.web.multipart.MultipartFile file, @Nullable String folderName, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Validates the uploaded file and creates a URL for it.

      Intended to be overridden if there is some different validation or custom business logic required. For example, if an asset with the same URL already exists, the current implementation increments the file name with an increasing integer, like filename-1.txt. An alternate implementation may want to simply throw FileUploadBadRequestException.

      Parameters:
      file - the uploaded file
      folderName - the folder name/path for the uploaded file
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      the created url
      Throws:
      org.springframework.web.multipart.MaxUploadSizeExceededException - if the file is too large
      FileUploadBadRequestException - if the mime type of the file is not supported
      IllegalArgumentException - if the filename is invalid
    • isWhitelistedMimeType

      protected boolean isWhitelistedMimeType(String mimeType)
    • createUniqueUrlFromFilename

      protected String createUniqueUrlFromFilename(String filename, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Creates a URL for the given filename. If the URL is found to be in use by another asset, it is suffixed with an incrementing integer value. For example, "/url.txt" becomes "/url-1.txt", and a subsequent creation would become "/url-2.txt".

      Delegates to AssetUrlGenerationHelper.createUrl(String, String) and AssetUrlGenerationHelper.applyIncrementingSuffix(String, ContextInfo).

      Parameters:
      filename - the filename for which a URL should be created. Does not have to be cleaned/normalized - this method will do that.
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      a unique URL for the given filename
      Throws:
      IllegalArgumentException - if the filename is invalid
    • createUniqueUrlFromFilename

      protected String createUniqueUrlFromFilename(String filename, @Nullable String folderName, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Creates a URL for the given filename. If the URL is found to be in use by another asset, it is suffixed with an incrementing integer value. For example, "/url.txt" becomes "/url-1.txt", and a subsequent creation would become "/url-2.txt".

      Delegates to AssetUrlGenerationHelper.createUrl(String, String) and AssetUrlGenerationHelper.applyIncrementingSuffix(String, ContextInfo).

      Parameters:
      filename - the filename for which a URL should be created. Does not have to be cleaned/normalized - this method will do that.
      folderName - the folder name/path for which an asset's URL will be created with
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      a unique URL for the given filename
      Throws:
      IllegalArgumentException - if the filename is invalid
    • validateIndividualAssetSize

      protected void validateIndividualAssetSize(long individualSizeInBytes)
    • exceedsMaxIndividualAssetSize

      protected boolean exceedsMaxIndividualAssetSize(long individualAssetSizeInBytes)
    • validateZipFileSize

      protected void validateZipFileSize(long zipSizeInBytes)
    • exceedsMaxZipFileSize

      protected boolean exceedsMaxZipFileSize(long zipSizeInBytes)
    • getMimeType

      protected String getMimeType(org.springframework.web.multipart.MultipartFile file)
    • getMimeType

      protected String getMimeType(String fileName)
    • generateAssetForUploadRequest

      protected Asset generateAssetForUploadRequest(@Nullable Asset assetRequest, String mimeType, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Generates a new Asset object for an upload using the mime type and optional properties provided in assetRequest.
      Parameters:
      assetRequest - (optional) an asset supplied in the original request containing properties that should be copied into the newly created Asset
      mimeType - the mime type of the file corresponding to this asset
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      a new Asset object with its fields initialized based upon the given file and assetRequest
      See Also:
    • mapEligibleProperties

      protected void mapEligibleProperties(Asset targetAsset, @Nullable Asset source)
      If source is present, will copy its Asset.getTags(), Asset.getFolderId() and Asset.getLocale() to targetAsset.
      Parameters:
      targetAsset - the asset whose properties should be set
      source - the asset from which properties should be derived
    • unzipAndUploadResourcesAsync

      @Deprecated public void unzipAndUploadResourcesAsync(File sourceZipFile, String fileUploadStateId, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg)
      Deprecated.
      Description copied from interface: StorageService
      Asynchronously upload the individual contents of a zip file to the storage provider, and create all necessary Folders and Assets in the data store for them. This method updates the FileUploadState with id fileUploadStateId with the status of upload.

      Certain validations are done in a way that, if not satisfied, cause the entire contents of the zip to fail to upload. These include:

      Specified by:
      unzipAndUploadResourcesAsync in interface StorageService
      Parameters:
      sourceZipFile - a temporary zip file whose contents should be unzipped and uploaded to the storage provider. This file itself will be deleted following this operation. If the file passes validation and InternalAssetProperties.isStoreZipFileOnProvider() is true, then a copy of the zip file will be uploaded to the provider.
      fileUploadStateId - the context ID of the base FileUploadState for this operation. The results of this upload attempt will be updated on this entity.
      assetRequest - (optional) asset from which to derive certain attributes when creating the final Assets for the files. Currently, Asset.tags, Asset.locale, and Asset.folderId are used. If supplied, Asset.folderId is used as the root folder under which all other folders/assets will be created.
      contextInfo - request context information around sandbox and multitenant state
      optimizeImg - whether or not to optimize the images
    • unzipAndUploadResourcesAsync

      @Async("uploadResourcesExecutor") public void unzipAndUploadResourcesAsync(File sourceZipFile, String fileUploadStateId, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg, boolean ignoreFolderName)
      Description copied from interface: StorageService
      Asynchronously upload the individual contents of a zip file to the storage provider, and create all necessary Folders and Assets in the data store for them. This method updates the FileUploadState with id fileUploadStateId with the status of upload.

      Certain validations are done in a way that, if not satisfied, cause the entire contents of the zip to fail to upload. These include:

      Specified by:
      unzipAndUploadResourcesAsync in interface StorageService
      Parameters:
      sourceZipFile - a temporary zip file whose contents should be unzipped and uploaded to the storage provider. This file itself will be deleted following this operation. If the file passes validation and InternalAssetProperties.isStoreZipFileOnProvider() is true, then a copy of the zip file will be uploaded to the provider.
      fileUploadStateId - the context ID of the base FileUploadState for this operation. The results of this upload attempt will be updated on this entity.
      assetRequest - (optional) asset from which to derive certain attributes when creating the final Assets for the files. Currently, Asset.tags, Asset.locale, and Asset.folderId are used. If supplied, Asset.folderId is used as the root folder under which all other folders/assets will be created.
      contextInfo - request context information around sandbox and multitenant state
      optimizeImg - whether or not to optimize the images
      ignoreFolderName - whether or not to include the parent folder path in the URI resolution of the files within the zip
    • validateZipAndReturnErrorMessage

      @Nullable protected String validateZipAndReturnErrorMessage(File sourceZipFile) throws IOException
      Validates that the given file does not exceed the InternalAssetProperties.getMaxZipFileSize(), and validates the individual files inside as described in validateEntriesInZip(File).
      Returns:
      the error message if there was a validation failure. Will be null if there was no validation failure.
      Throws:
      IOException - if there was an error reading the file
    • buildErrorMessage

      protected String buildErrorMessage(@NonNull @NonNull List<DefaultStorageService.ZipEntryValidationError> errors)
    • validateEntriesInZip

      protected List<DefaultStorageService.ZipEntryValidationError> validateEntriesInZip(File sourceZipFile) throws IOException
      Reads and validates all of the non-directory (and non-ignored) entries in the given zip file.
      Parameters:
      sourceZipFile - the zip file to read
      Returns:
      a list of all validation errors that were encountered with entries. Will be empty if no errors were found.
      Throws:
      IOException - if there was an error reading the file
      See Also:
    • validateEntryName

      @Nullable protected DefaultStorageService.ZipEntryValidationError validateEntryName(String filename)
      Validates that the filename of the Zip entry does not contain any path traversals.
      Parameters:
      filename - the file name of the Zip entry
      Returns:
      the validation error if one was detected, null otherwise
    • validateEntry

      @Nullable protected DefaultStorageService.ZipEntryValidationError validateEntry(ZipEntry entry, ZipInputStream zipInputStream) throws IOException
      Reads the entry and validates its mime type and size are acceptable.
      Parameters:
      entry - basic information about the entry itself. This entry is guaranteed not to be a directory or a resource that should be ignored.
      zipInputStream - a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.
      Returns:
      the validation error if one was detected, null otherwise
      Throws:
      IOException - if there was an error reading the file
    • readEntryAndReturnIfSizeExceedsLimit

      protected boolean readEntryAndReturnIfSizeExceedsLimit(ZipInputStream zipInputStream) throws IOException
      Reads and counts the byte size of the current entry in the zip input stream, reporting if the size exceeds the InternalAssetProperties.getMaxIndividualAssetSize().
      Parameters:
      zipInputStream - a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.
      Returns:
      true if the entry's size exceeds the maximum limit, false otherwise
      Throws:
      IOException - if there was an error reading the file
    • getIndividualAssetTooLargeErrorMessage

      protected String getIndividualAssetTooLargeErrorMessage()
    • getZipTooLargeErrorMessage

      protected String getZipTooLargeErrorMessage()
    • getMimeTypeNotSupportedErrorMessage

      protected String getMimeTypeNotSupportedErrorMessage(String mimeType)
    • setUploadStatus

      protected void setUploadStatus(FileUploadState uploadState, BulkAddResourcesResponse bulkAddResourcesResponse)
    • handleExceptionWithZipFile

      protected void handleExceptionWithZipFile(FileUploadState uploadState, String zipFileName, Exception e, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • handleFailedValidationWithZipFile

      protected void handleFailedValidationWithZipFile(FileUploadState uploadState, String zipFileName, String errorMessage, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • validateZipResource

      public void validateZipResource(@NonNull @NonNull org.springframework.web.multipart.MultipartFile file)
      Description copied from interface: StorageService
      A simple method intended to be used to pre-validate a MultipartFile received in an API request when expecting a zip file.

      While methods like StorageService.unzipAndUploadResourcesAsync(File, String, Asset, ContextInfo, boolean) do perform certain validations, this method is intended to allow immediate rejection of invalid requests before getting too far in the flow.

      Default validations:

      Specified by:
      validateZipResource in interface StorageService
      Parameters:
      file - the file to validate
    • isZipType

      protected boolean isZipType(String mimeType)
    • processZipExtractionResult

      @Deprecated protected void processZipExtractionResult(DefaultStorageService.ZipExtractionResult zipExtractionResult, FileUploadState uploadState, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg)
      Deprecated.
      Given a DefaultStorageService.ZipExtractionResult, creates all of the necessary Folders in the data store, uploads the extracted files to the storage provider (after optimizing them if necessary), and creates Assets in the data store for all successfully uploaded files.

      The FileUploadState will be updated in the data store to reflect the final status of the operation.

      This method guarantees that the DefaultStorageService.ZipExtractionResult.temporaryDirectoryFilesWereExtractedTo and all of its contents will be deleted regardless of success or failure.

      Parameters:
      zipExtractionResult - an object containing the results of extracting a zip file
      uploadState - the FileUploadState from the data store corresponding to this zip upload/extract operation. Will be updated and sent to the data store with the final status of this operation.
      assetRequest - (optional) the caller-requested asset details from which to derive certain attributes when creating the final assets/folders for the files
      contextInfo - request context information around multitenant state
      optimizeImg - if true, the extracted files will be optimized before being uploaded to the storage provider
    • processZipExtractionResult

      protected void processZipExtractionResult(DefaultStorageService.ZipExtractionResult zipExtractionResult, FileUploadState uploadState, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean optimizeImg, boolean ignoreFolderName)
      Given a DefaultStorageService.ZipExtractionResult, creates all of the necessary Folders in the data store, uploads the extracted files to the storage provider (after optimizing them if necessary), and creates Assets in the data store for all successfully uploaded files.

      The FileUploadState will be updated in the data store to reflect the final status of the operation.

      This method guarantees that the DefaultStorageService.ZipExtractionResult.temporaryDirectoryFilesWereExtractedTo and all of its contents will be deleted regardless of success or failure.

      Parameters:
      zipExtractionResult - an object containing the results of extracting a zip file
      uploadState - the FileUploadState from the data store corresponding to this zip upload/extract operation. Will be updated and sent to the data store with the final status of this operation.
      assetRequest - (optional) the caller-requested asset details from which to derive certain attributes when creating the final assets/folders for the files
      contextInfo - request context information around multitenant state
      optimizeImg - if true, the extracted files will be optimized before being uploaded to the storage provider
      ignoreFolderName - if true, the extracted files' URIs will not contain their parent folder paths
    • createAllFolders

      protected Map<String,Folder> createAllFolders(Map<String,Folder> foldersToCreateByNormalizedPath, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, @Nullable Asset assetRequest)
      Creates all of the given Folders in the data store, and returns the created items.

      This method sets the Folder.getParentFolderId() on each folder as determined by the directory paths to mimic the same hierarchy. For top-level folders whose directory paths have no parent, the Folder.getParentFolderId() will either be null or Asset.getFolderId() if provided in the assetRequest.

      Parameters:
      foldersToCreateByNormalizedPath - the map of normalized directory paths to Folder objects that should be created
      contextInfo - context information surrounding multitenant state
      assetRequest - the caller-requested asset details
      Returns:
      a map from normalized folder names to created Folder objects
    • getParentFolderId

      @Nullable protected String getParentFolderId(String normalizedPath, Map<String,Folder> createdFoldersByNormalizedPath, @Nullable Asset assetRequest)
      Gets the parent directory path from normalizedPath, gets the Folder for that parent directory path in createdFoldersByNormalizedPath, and returns its Folder.getId().

      Alternatively, if this path does not have a parent directory and assetRequest was supplied, the Asset.getFolderId() from the request will be used instead. This way any "root level" items will have that folder ID as their parent.

      Parameters:
      normalizedPath - the normalized path of the directory or file whose parent folder needs to be determined
      createdFoldersByNormalizedPath - a map from normalized directory names to created Folders. Used to find the corresponding Folder for the parent directory path.
      assetRequest - the caller-requested asset details
      Returns:
      the Folder.getId() of the Folder for the parent directory, or null if this item does not have a parent directory
    • getParentDirectoryPath

      @Nullable protected String getParentDirectoryPath(String normalizedPath)
      Gets the parent directory path from the given normalized path.
      Parameters:
      normalizedPath - the normalized path of a file or directory. For example, "directory/" or "directory" or "directory/file.txt".
      Returns:
      the path for this path's parent directory, or null if this path does not have a parent
    • batchOptimizeFiles

      protected void batchOptimizeFiles(Map<String,File> filesToOptimizeByNormalizedPath)
      Delegates to ImageOperationService to optimize the given files as a batch. The optimization will write over the given files.
      Parameters:
      filesToOptimizeByNormalizedPath - a map of normalized file paths to file objects
    • generateContextDiscriminatedUniqueUrls

      @Deprecated protected Map<String,String> generateContextDiscriminatedUniqueUrls(Collection<String> filePaths, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Deprecated.
      Given a collection of file names, generates a unique URL for each with a context-discrimination prefix that's suitable for being supplied to the storage provider.
      Parameters:
      filePaths - file names for which context discriminated unique URLs need to be created. Do not have to be cleaned/normalized - this method will do that.
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      mappings from given file names to the unique urls that were generated for them
    • generateContextDiscriminatedUniqueUrls

      protected Map<String,String> generateContextDiscriminatedUniqueUrls(Collection<String> filePaths, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo, boolean ignoreFolderName)
      Given a collection of file names, generates a unique URL for each with a context-discrimination prefix that's suitable for being supplied to the storage provider.
      Parameters:
      filePaths - file names for which context discriminated unique URLs need to be created. Do not have to be cleaned/normalized - this method will do that.
      contextInfo - context information surrounding sandboxing and multitenant state
      ignoreFolderName - if true, the generated URIs for the given file paths will not include their parent folder paths
      Returns:
      mappings from given file names to the unique urls that were generated for them
    • generateContextDiscriminatedUniqueUrl

      protected String generateContextDiscriminatedUniqueUrl(String filePath, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Given a file path, generate a unique URL with a context-discrimination prefix that's suitable for being supplied to the storage provider.
      Parameters:
      filePath - a file name for which a context discriminated unique URL needs to be created. Does not have to be cleaned/normalized - this method will do that.
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      a unique context discriminated URL that was generated for the given path
    • generateContextDiscriminatedUniqueUrl

      protected String generateContextDiscriminatedUniqueUrl(String filePath, @Nullable String folderName, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Given a file path, generate a unique URL with a context-discrimination prefix that's suitable for being supplied to the storage provider.
      Parameters:
      filePath - a file name for which a context discriminated unique URL needs to be created. Does not have to be cleaned/normalized - this method will do that.
      folderName - the folder name/path of the file used to create the unique URL
      contextInfo - context information surrounding sandboxing and multitenant state
      Returns:
      a unique context discriminated URL that was generated for the given path
    • createAssetsForSuccessfullyUploadedFiles

      protected List<Asset> createAssetsForSuccessfullyUploadedFiles(DefaultStorageService.ZipExtractionResult zipExtractionResult, Map<String,String> contextDiscriminatedUrlsByNormalizedPath, Map<String,Folder> createdFoldersByNormalizedPath, BulkAddResourcesResponse addResourcesResponse, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Creates Assets in the data store for the files that were successfully uploaded to the storage provider. This method takes BulkAddResourcesResponse.getGivenFilenamesToSuccessfullyCreatedPaths(), maps those back to the originally extracted files from DefaultStorageService.ZipExtractionResult.getFilesByNormalizedPath(), and then builds/inserts the assets in the data store.
      Parameters:
      zipExtractionResult - an object containing the results of extracting the original zip file
      contextDiscriminatedUrlsByNormalizedPath - mappings from the original normalized path names of files to the unique urls that were generated for them. Keys should correspond to keys in DefaultStorageService.ZipExtractionResult.getFilesByNormalizedPath(), and values should correspond to keys in BulkAddResourcesResponse.getGivenFilenamesToSuccessfullyCreatedPaths().
      createdFoldersByNormalizedPath - a map from normalized directory names to created Folders. Used to find the corresponding Folder for the parent directory path of a file's normalized path.
      addResourcesResponse - the response returned by the storage provider describing which file uploads succeeded and which failed
      assetRequest - (optional) the caller-requested asset details from which to derive certain attributes when creating the final assets for the files.
      contextInfo - context information surrounding multitenant state
      Returns:
      the list of all assets that were created in the data store. Will not be null, but may be empty if there were no successfully uploaded files.
    • generateAssetsForFiles

      protected List<Asset> generateAssetsForFiles(Stream<Map.Entry<String,File>> filesByNormalizedPath, Map<String,String> contextDiscriminatedUrlsByNormalizedPath, Map<String,Folder> createdFoldersByNormalizedPath, @Nullable Asset assetRequest, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
    • getFailedNormalizedFilePaths

      protected Set<String> getFailedNormalizedFilePaths(DefaultStorageService.ZipExtractionResult zipExtractionResult, BulkAddResourcesResponse addResourcesResponse, Map<String,String> contextDiscriminatedUrlsByNormalizedPath)
    • storeMultipartFile

      @Deprecated(since="2.0.1", forRemoval=true) protected File storeMultipartFile(String url, org.springframework.web.multipart.MultipartFile file, boolean optimizeImg)
      Deprecated, for removal: This API element is subject to removal in a future version.
    • storeMultipartFileResource

      protected ResourceWithMetadata storeMultipartFileResource(String url, org.springframework.web.multipart.MultipartFile file, boolean optimizeImg)
    • storeFile

      @Deprecated(since="2.0.1", forRemoval=true) protected File storeFile(String url, InputStream fileInputStream, String fileName)
      Deprecated, for removal: This API element is subject to removal in a future version.
    • storeResource

      protected ResourceWithMetadata storeResource(String url, InputStream inputStream, String fileName)
    • removeFile

      @Deprecated(since="1.7.6", forRemoval=true) public void removeFile(String filename)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Description copied from interface: StorageService
      Remove the provided file from the storage provider.
      Specified by:
      removeFile in interface StorageService
      Parameters:
      filename - the name of the file to delete on the storage provider
    • removeFile

      public void removeFile(String filename, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Description copied from interface: StorageService
      Remove the provided file from the storage provider.
      Specified by:
      removeFile in interface StorageService
      Parameters:
      filename - the name of the file to delete on the storage provider
      contextInfo - context of the request: information around sandbox and multitenant state
    • extractZip

      protected DefaultStorageService.ZipExtractionResult extractZip(File zipFile, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo) throws IOException
      Extracts the contents of the zip file to a temporary directory, building any Folder objects for directories and creating temporary files for extracted files.

      This method guarantees that the temporary extraction directory and its contents will be wiped if an error is encountered.

      Parameters:
      zipFile - The zip file to extract
      contextInfo - context information surrounding multitenant state
      Returns:
      details about the extracted folders and files
      Throws:
      IOException - if there was an IO problem extracting the file.
    • matchesAnyResourceNameToIgnore

      protected boolean matchesAnyResourceNameToIgnore(String resourceName)
    • buildFolderAndPutInMap

      protected void buildFolderAndPutInMap(String directoryPath, Map<String,Folder> foldersByNormalizedPath, @Nullable com.broadleafcommerce.data.tracking.core.context.ContextInfo contextInfo)
      Given a directory path that was found in a zip file, build a Folder for it and put it in the given foldersByPath map.

      The path of the directory is first cleaned and normalized. This is used as the key for foldersByPath.

      The last segment of the normalized path is then set as the Folder.getName().

      This method does not initialize Folder.getParentFolderId(), as that is done in a later step in createAllFolders(Map, ContextInfo, Asset) when the entities are created.

      Parameters:
      directoryPath - the full name of the directory (with path information) as found in the zip entry
      foldersByNormalizedPath - a map of normalized folder names to Folder objects (as described in DefaultStorageService.ZipExtractionResult.getFoldersByNormalizedPath()) which the new folder should be placed in
      contextInfo - context information surrounding multitenant state
    • extractToFileAndPutInMap

      protected void extractToFileAndPutInMap(String entryPath, Path tempDirectoryForExtraction, ZipInputStream zipInputStream, Map<String,File> filesByNormalizedPath) throws IOException
      Creates a new file inside of tempDirectoryForExtraction, extracts the current zip entry's data to it via extractCurrentEntryToFile(ZipInputStream, File), and then puts the appropriate mapping in filesByPath.

      The path of the zip entry is first cleaned and normalized, and then used as the key for filesByPath.

      Parameters:
      entryPath - the original name of the zip entry
      tempDirectoryForExtraction - the temporary directory in which to write the extracted file
      zipInputStream - a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.
      filesByNormalizedPath - a map of normalized file names to File objects (as described in DefaultStorageService.ZipExtractionResult.getFilesByNormalizedPath()) which the extracted file should be placed in
      Throws:
      IOException - if there was an error reading/writing data
    • extractCurrentEntryToFile

      protected void extractCurrentEntryToFile(ZipInputStream zipInputStream, File extractionTarget) throws IOException
      Reads the current zip entry's data and writes it to the extractionTarget.
      Parameters:
      zipInputStream - a zip input stream already positioned at the start of a zip entry's data. Should not be closed by this method.
      extractionTarget - the file to which the zip entry's data should be written
      Throws:
      IOException - if there was an error reading/writing the data
    • addAttributesToAsset

      public void addAttributesToAsset(@NonNull @NonNull Asset asset, @NonNull @NonNull File file)
      Responsible for adding any attributes to the asset that are derived from the uploaded file.
      Specified by:
      addAttributesToAsset in interface StorageService
      Parameters:
      asset - the asset to which to add attributes
      file - the file from which to derive attributes
    • addImageAttributes

      protected void addImageAttributes(@NonNull @NonNull Asset asset, @NonNull @NonNull Dimension imageDimension)
    • addAttributesToAsset

      public void addAttributesToAsset(@NonNull @NonNull Asset asset, @NonNull @NonNull ResourceWithMetadata resource)
      Responsible for adding any attributes to the asset that are derived from the uploaded Resource.
      Specified by:
      addAttributesToAsset in interface StorageService
      Parameters:
      asset - the asset to which to add attributes
      resource - the ResourceWithMetadata from which to derive attributes
    • getAssetDimensions

      protected Optional<Dimension> getAssetDimensions(@NonNull @NonNull File assetFile)
      Gets dimensions for given asset file
      Parameters:
      assetFile - asset file
      Returns:
      dimensions of the asset, null if no dimensions found
      Since:
      2.1.3
    • getAssetDimensions

      protected Optional<Dimension> getAssetDimensions(@NonNull @NonNull ResourceWithMetadata videoResource)
      Gets dimensions for given asset ResourceWithMetadata
      Parameters:
      videoResource - an asset ResourceWithMetadata
      Returns:
      dimensions of the asset or Optional.empty() if no dimensions found
      Since:
      2.1.3
    • getImageDimensions

      @Deprecated(since="2.1.3", forRemoval=true) protected Optional<Dimension> getImageDimensions(@NonNull @NonNull File assetFile)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Gets image dimensions for given asset file
      Parameters:
      assetFile - asset file
      Returns:
      dimensions of image, null if not an image
    • getImageDimensions

      @Deprecated(since="2.1.3", forRemoval=true) protected Optional<Dimension> getImageDimensions(@NonNull @NonNull ResourceWithMetadata imageResource)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Gets image dimensions for given asset ResourceWithMetadata
      Parameters:
      imageResource - an asset ResourceWithMetadata
      Returns:
      dimensions of image or Optional.empty() if not an image
    • getImageDimensions

      @Deprecated(since="2.1.3", forRemoval=true) protected Optional<Dimension> getImageDimensions(@NonNull @NonNull ImageInputStream imageInputStream)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Gets image dimensions for given asset ImageInputStream
      Parameters:
      imageInputStream - an asset ImageInputStream
      Returns:
      dimensions of image or Optional.empty() if not an image
    • getAssetDimensions

      protected Optional<Dimension> getAssetDimensions(@NonNull @NonNull InputStream fileInputStream)
      Gets dimensions for given asset InputStream
      Parameters:
      fileInputStream - an asset InputStream
      Returns:
      dimensions of the asset or Optional.empty() if no dimensions found
      Since:
      2.1.3
    • getMimeFileTypeMap

      @NonNull protected jakarta.activation.FileTypeMap getMimeFileTypeMap()
    • getAssetUrlGenerationHelper

      @NonNull protected AssetUrlGenerationHelper getAssetUrlGenerationHelper()
    • getAssetStorageUtils

      protected AssetStorageUtils getAssetStorageUtils()
    • setAssetStorageUtils

      @Autowired public void setAssetStorageUtils(AssetStorageUtils assetStorageUtils)