From 81c47c2b04c94e58dd936ffcc078a99015f6257d Mon Sep 17 00:00:00 2001 From: bsayan2 Date: Tue, 17 Jun 2025 14:13:41 +0530 Subject: [PATCH] MNT-24883 adding source file name to transform options Added source file name to transform options if exist in nodeService. It will be used in ATS to maintain consistency in transform for filenames. --- .../transform/base/fs/FileManager.java | 80 ++++-- .../base/transform/ProcessHandler.java | 83 +++--- .../base/transform/TransformManagerImpl.java | 54 +++- .../src/main/resources/templates/test.html | 1 + .../base/TransformControllerAllInOneTest.java | 188 ++++++------ .../base/TransformControllerTest.java | 268 +++++++++--------- .../base/transform/StreamHandlerTest.java | 110 ++++--- .../transform/common/RequestParamMap.java | 4 + .../transform/config/CoreFunction.java | 14 +- .../config/CoreVersionDecorator.java | 136 +++++---- .../registry/TransformRegistryHelper.java | 122 ++++---- .../config/CoreVersionDecoratorTest.java | 140 ++++++++- 12 files changed, 706 insertions(+), 494 deletions(-) diff --git a/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java b/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java index bb1b5631..f1575bea 100644 --- a/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java +++ b/engines/base/src/main/java/org/alfresco/transform/base/fs/FileManager.java @@ -2,7 +2,7 @@ * #%L * Alfresco Transform Core * %% - * Copyright (C) 2005 - 2023 Alfresco Software Limited + * Copyright (C) 2005 - 2025 Alfresco Software Limited * %% * This file is part of the Alfresco software. * - @@ -26,16 +26,16 @@ */ package org.alfresco.transform.base.fs; -import org.alfresco.transform.base.logging.LogEntry; -import org.alfresco.transform.common.ExtensionService; -import org.alfresco.transform.exceptions.TransformException; -import org.springframework.core.io.Resource; -import org.springframework.core.io.UrlResource; -import org.springframework.http.ResponseEntity; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.util.UriUtils; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; + +import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.util.StringUtils.getFilename; + +import static org.alfresco.transform.common.ExtensionService.getExtensionForMimetype; -import jakarta.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -43,14 +43,19 @@ import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Files; +import java.util.UUID; +import jakarta.servlet.http.HttpServletRequest; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static org.alfresco.transform.common.ExtensionService.getExtensionForMimetype; -import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.INSUFFICIENT_STORAGE; -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; -import static org.springframework.util.StringUtils.getFilename; +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.http.ResponseEntity; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.util.UriUtils; + +import org.alfresco.transform.base.logging.LogEntry; +import org.alfresco.transform.common.ExtensionService; +import org.alfresco.transform.exceptions.TransformException; public class FileManager { @@ -58,16 +63,19 @@ public class FileManager public static final String TARGET_FILE = "targetFile"; private FileManager() - { - } + {} - public static File createSourceFile(HttpServletRequest request, InputStream inputStream, String sourceMimetype) + public static File createSourceFile(HttpServletRequest request, InputStream inputStream, String sourceMimetype, String sourceFileName) { try { - String extension = "."+getExtensionForMimetype(sourceMimetype); - File file = TempFileProvider.createTempFile("source_", extension); + String extension = "." + getExtensionForMimetype(sourceMimetype); + File file = StringUtils.isEmpty(sourceFileName) + ? TempFileProvider.createTempFile("source_", extension) + : TempFileProvider.createFileWithinUUIDTempDir(sourceFileName); + Files.copy(inputStream, file.toPath(), REPLACE_EXISTING); + if (request != null) { request.setAttribute(SOURCE_FILE, file); @@ -85,7 +93,7 @@ public class FileManager { try { - String extension = "."+ExtensionService.getExtensionForTargetMimetype(targetMimetype, sourceMimetype); + String extension = "." + ExtensionService.getExtensionForTargetMimetype(targetMimetype, sourceMimetype); File file = TempFileProvider.createTempFile("target_", extension); if (request != null) { @@ -120,20 +128,20 @@ public class FileManager else { throw new TransformException(INTERNAL_SERVER_ERROR, - "Could not read the target file: " + file.getPath()); + "Could not read the target file: " + file.getPath()); } } catch (MalformedURLException e) { throw new TransformException(INTERNAL_SERVER_ERROR, - "The target filename was malformed: " + file.getPath(), e); + "The target filename was malformed: " + file.getPath(), e); } } public static InputStream getMultipartFileInputStream(MultipartFile sourceMultipartFile) { InputStream inputStream; - if (sourceMultipartFile == null) + if (sourceMultipartFile == null) { throw new TransformException(BAD_REQUEST, "Required request part 'file' is not present"); } @@ -192,7 +200,7 @@ public class FileManager // targetFilename should never be null (will be "transform."+), so we should not worry about encodePath(null) targetFilename = UriUtils.encodePath(getFilename(targetFilename), "UTF-8"); return ResponseEntity.ok().header(CONTENT_DISPOSITION, - "attachment; filename*=UTF-8''" + targetFilename).body(targetResource); + "attachment; filename*=UTF-8''" + targetFilename).body(targetResource); } /** @@ -201,8 +209,7 @@ public class FileManager public static class TempFileProvider { private TempFileProvider() - { - } + {} public static File createTempFile(final String prefix, final String suffix) { @@ -214,11 +221,22 @@ public class FileManager catch (IOException e) { throw new RuntimeException( - "Failed to created temp file: \n prefix: " + prefix + - "\n suffix: " + suffix + "\n directory: " + directory, e); + "Failed to created temp file: \n prefix: " + prefix + + "\n suffix: " + suffix + "\n directory: " + directory, + e); } } + public static File createFileWithinUUIDTempDir(String sourceFileName) + { + File tempDir = new File(getTempDir(), UUID.randomUUID().toString()); + if (!tempDir.mkdirs() && !tempDir.exists()) + { + throw new TransformException(INSUFFICIENT_STORAGE, "Failed to create temp directory: " + tempDir); + } + return new File(tempDir, sourceFileName); + } + private static File getTempDir() { final String dirName = "Alfresco"; diff --git a/engines/base/src/main/java/org/alfresco/transform/base/transform/ProcessHandler.java b/engines/base/src/main/java/org/alfresco/transform/base/transform/ProcessHandler.java index 132be315..80e063a1 100644 --- a/engines/base/src/main/java/org/alfresco/transform/base/transform/ProcessHandler.java +++ b/engines/base/src/main/java/org/alfresco/transform/base/transform/ProcessHandler.java @@ -2,7 +2,7 @@ * #%L * Alfresco Transform Core * %% - * Copyright (C) 2022 - 2023 Alfresco Software Limited + * Copyright (C) 2022 - 2025 Alfresco Software Limited * %% * This file is part of the Alfresco software. * - @@ -26,19 +26,12 @@ */ package org.alfresco.transform.base.transform; -import org.alfresco.transform.base.CustomTransformer; -import org.alfresco.transform.base.TransformController; -import org.alfresco.transform.base.logging.LogEntry; -import org.alfresco.transform.base.probes.ProbeTransform; -import org.alfresco.transform.base.registry.CustomTransformers; -import org.alfresco.transform.client.model.TransformRequest; -import org.alfresco.transform.exceptions.TransformException; -import org.alfresco.transform.common.TransformerDebug; -import org.alfresco.transform.registry.TransformServiceRegistry; -import org.springframework.web.multipart.MultipartFile; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; +import static org.springframework.http.HttpStatus.OK; + +import static org.alfresco.transform.common.RequestParamMap.*; -import jakarta.jms.Destination; -import jakarta.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.Arrays; @@ -46,30 +39,32 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import jakarta.jms.Destination; +import jakarta.servlet.http.HttpServletRequest; -import static org.alfresco.transform.common.RequestParamMap.DIRECT_ACCESS_URL; -import static org.alfresco.transform.common.RequestParamMap.SOURCE_EXTENSION; -import static org.alfresco.transform.common.RequestParamMap.SOURCE_MIMETYPE; -import static org.alfresco.transform.common.RequestParamMap.TARGET_EXTENSION; -import static org.alfresco.transform.common.RequestParamMap.TARGET_MIMETYPE; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; -import static org.springframework.http.HttpStatus.OK; +import org.springframework.web.multipart.MultipartFile; + +import org.alfresco.transform.base.CustomTransformer; +import org.alfresco.transform.base.TransformController; +import org.alfresco.transform.base.logging.LogEntry; +import org.alfresco.transform.base.probes.ProbeTransform; +import org.alfresco.transform.base.registry.CustomTransformers; +import org.alfresco.transform.client.model.TransformRequest; +import org.alfresco.transform.common.TransformerDebug; +import org.alfresco.transform.exceptions.TransformException; +import org.alfresco.transform.registry.TransformServiceRegistry; /** - * Provides the transform logic common to http (upload/download), message and probe requests. See - * {@link TransformHandler#handleHttpRequest(HttpServletRequest, MultipartFile, String, String, Map, ProbeTransform)}, - * {@link TransformHandler#handleMessageRequest(TransformRequest, Long, Destination, ProbeTransform)} and - * {@link TransformHandler#handleProbeRequest(String, String, Map, File, File, ProbeTransform)}. Note the handing of transform requests - * via a message queue is the same as via the {@link TransformController#transform(TransformRequest, Long, Destination)}. + * Provides the transform logic common to http (upload/download), message and probe requests. See {@link TransformHandler#handleHttpRequest(HttpServletRequest, MultipartFile, String, String, Map, ProbeTransform)}, {@link TransformHandler#handleMessageRequest(TransformRequest, Long, Destination, ProbeTransform)} and {@link TransformHandler#handleProbeRequest(String, String, Map, File, File, ProbeTransform)}. Note the handing of transform requests via a message queue is the same as via the {@link TransformController#transform(TransformRequest, Long, Destination)}. */ abstract class ProcessHandler extends FragmentHandler { private static final List NON_TRANSFORM_OPTION_REQUEST_PARAMETERS = Arrays.asList(SOURCE_EXTENSION, - TARGET_EXTENSION, TARGET_MIMETYPE, SOURCE_MIMETYPE, DIRECT_ACCESS_URL); + TARGET_EXTENSION, TARGET_MIMETYPE, SOURCE_MIMETYPE, DIRECT_ACCESS_URL, SOURCE_FILENAME); protected final String sourceMimetype; protected final String targetMimetype; + protected final String sourceFileName; private final Map transformOptions; protected String reference; private final TransformServiceRegistry transformRegistry; @@ -78,11 +73,12 @@ abstract class ProcessHandler extends FragmentHandler private final CustomTransformers customTransformers; ProcessHandler(String sourceMimetype, String targetMimetype, Map transformOptions, - String reference, TransformServiceRegistry transformRegistry, TransformerDebug transformerDebug, - ProbeTransform probeTransform, CustomTransformers customTransformers) + String reference, TransformServiceRegistry transformRegistry, TransformerDebug transformerDebug, + ProbeTransform probeTransform, CustomTransformers customTransformers) { this.sourceMimetype = sourceMimetype; this.targetMimetype = targetMimetype; + this.sourceFileName = transformOptions.getOrDefault(SOURCE_FILENAME, null); this.transformOptions = cleanTransformOptions(transformOptions); this.reference = reference; @@ -107,7 +103,6 @@ abstract class ProcessHandler extends FragmentHandler super.init(); } - public String getReference() { return reference; @@ -118,6 +113,7 @@ abstract class ProcessHandler extends FragmentHandler LogEntry.start(); transformManager.setSourceMimetype(sourceMimetype); transformManager.setTargetMimetype(targetMimetype); + transformManager.setSourceFileName(sourceFileName); probeTransform.incrementTransformerCount(); try { @@ -131,13 +127,13 @@ abstract class ProcessHandler extends FragmentHandler } catch (TransformException e) { - transformerDebug.logFailure(reference, " Error: "+e.getMessage()); + transformerDebug.logFailure(reference, " Error: " + e.getMessage()); LogEntry.setStatusCodeAndMessage(e.getStatus(), e.getMessage()); handleTransformException(e); } catch (Exception e) { - transformerDebug.logFailure(reference, " Error: "+e.getMessage()); + transformerDebug.logFailure(reference, " Error: " + e.getMessage()); LogEntry.setStatusCodeAndMessage(INTERNAL_SERVER_ERROR, e.getMessage()); handleException(e); } @@ -174,8 +170,7 @@ abstract class ProcessHandler extends FragmentHandler } protected void sendTransformResponse(TransformManagerImpl transformManager) - { - } + {} protected void handleTransformException(TransformException e) { @@ -188,19 +183,19 @@ abstract class ProcessHandler extends FragmentHandler } private String getTransformerName(final String sourceMimetype, long sourceSizeInBytes, final String targetMimetype, - final Map transformOptions) + final Map transformOptions) { final String transformerName = transformRegistry.findTransformerName(sourceMimetype, - sourceSizeInBytes, targetMimetype, transformOptions, null); + sourceSizeInBytes, targetMimetype, transformOptions, null); if (transformerName == null) { - throw new TransformException(BAD_REQUEST, "No transforms for: "+ - sourceMimetype+ - (sourceSizeInBytes >= 0 ? " ("+TransformerDebug.fileSize(sourceSizeInBytes)+")" : "")+ - " -> "+targetMimetype+ - transformOptions.entrySet().stream() - .map(entry -> entry.getKey()+"="+entry.getValue()) - .collect(Collectors.joining(", ", " ", ""))); + throw new TransformException(BAD_REQUEST, "No transforms for: " + + sourceMimetype + + (sourceSizeInBytes >= 0 ? " (" + TransformerDebug.fileSize(sourceSizeInBytes) + ")" : "") + + " -> " + targetMimetype + + transformOptions.entrySet().stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining(", ", " ", ""))); } return transformerName; } @@ -210,7 +205,7 @@ abstract class ProcessHandler extends FragmentHandler CustomTransformer customTransformer = customTransformers.get(transformName); if (customTransformer == null) { - throw new TransformException(INTERNAL_SERVER_ERROR, "Custom Transformer "+transformName+" not found"); + throw new TransformException(INTERNAL_SERVER_ERROR, "Custom Transformer " + transformName + " not found"); } return customTransformer; } diff --git a/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformManagerImpl.java b/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformManagerImpl.java index b6fcc945..65d325e3 100644 --- a/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformManagerImpl.java +++ b/engines/base/src/main/java/org/alfresco/transform/base/transform/TransformManagerImpl.java @@ -2,7 +2,7 @@ * #%L * Alfresco Transform Core * %% - * Copyright (C) 2005 - 2023 Alfresco Software Limited + * Copyright (C) 2005 - 2025 Alfresco Software Limited * %% * This file is part of the Alfresco software. * - @@ -26,18 +26,21 @@ */ package org.alfresco.transform.base.transform; -import org.alfresco.transform.base.TransformManager; -import org.alfresco.transform.base.fs.FileManager; -import org.alfresco.transform.base.util.OutputStreamLengthRecorder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import jakarta.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Locale; +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import org.alfresco.transform.base.TransformManager; +import org.alfresco.transform.base.fs.FileManager; +import org.alfresco.transform.base.util.OutputStreamLengthRecorder; /** * Manages the input and output streams and any temporary files that have been created. @@ -60,6 +63,17 @@ public class TransformManagerImpl implements TransformManager private boolean createTargetFileCalled; private Boolean startedWithSourceFile; private Boolean startedWithTargetFile; + private String sourceFileName; + + public String getSourceFileName() + { + return sourceFileName; + } + + public void setSourceFileName(String sourceFileName) + { + this.sourceFileName = sourceFileName; + } public void setRequest(HttpServletRequest request) { @@ -71,7 +85,8 @@ public class TransformManagerImpl implements TransformManager this.processHandler = processHandler; } - @Override public String getRequestId() + @Override + public String getRequestId() { return processHandler.getReference(); } @@ -149,7 +164,8 @@ public class TransformManagerImpl implements TransformManager keepTargetFile = true; } - @Override public File createSourceFile() + @Override + public File createSourceFile() { if (createSourceFileCalled) { @@ -159,12 +175,13 @@ public class TransformManagerImpl implements TransformManager if (sourceFile == null) { - sourceFile = FileManager.createSourceFile(request, inputStream, sourceMimetype); + sourceFile = FileManager.createSourceFile(request, inputStream, sourceMimetype, sourceFileName); } return sourceFile; } - @Override public File createTargetFile() + @Override + public File createTargetFile() { if (createTargetFileCalled) { @@ -204,8 +221,19 @@ public class TransformManagerImpl implements TransformManager { logger.error("Failed to delete temporary source file {}", sourceFile.getPath()); } + if (sourceFile != null) + { + File parentDir = sourceFile.getParentFile(); + if (parentDir != null + && !StringUtils.equalsAny(parentDir.getName().toLowerCase(Locale.ROOT), "alfresco", "temp", "tmp") + && !parentDir.delete()) + { + logger.error("Failed to delete parent directory {}", parentDir.getPath()); + } + } outputStreamLengthRecorder = null; sourceFile = null; + sourceFileName = null; createSourceFileCalled = false; startedWithSourceFile = null; } diff --git a/engines/base/src/main/resources/templates/test.html b/engines/base/src/main/resources/templates/test.html index d7d5fc77..0a5ea02d 100644 --- a/engines/base/src/main/resources/templates/test.html +++ b/engines/base/src/main/resources/templates/test.html @@ -10,6 +10,7 @@
+
file
sourceFilename
directAccessUrl
sourceMimetype