Add MultipartFile compatibility shim and swap common imports to it
This commit is contained in:
@@ -16,7 +16,7 @@ import org.slf4j.MDC;
|
||||
// MultipartFile) and PDFFile.getFileInput()/setFileInput(MultipartFile). Changing the type here
|
||||
// would ripple into FileStorage and PDFFile public signatures, so the original type is kept until
|
||||
// those collaborators are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package stirling.software.common.model;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Migration compatibility shim for Spring's {@code org.springframework.web.multipart.MultipartFile}.
|
||||
*
|
||||
* <p>Quarkus/JAX-RS has no drop-in equivalent for the {@code MultipartFile} abstraction that the
|
||||
* service layer relies on (it exposes {@code org.jboss.resteasy.reactive.multipart.FileUpload} at
|
||||
* the REST boundary instead). To avoid rewriting the public signatures of dozens of service and
|
||||
* util methods across every module, this interface mirrors the subset of Spring's API that the
|
||||
* codebase actually uses. Controllers adapt the inbound {@code FileUpload}/{@code byte[]} to one of
|
||||
* the implementations ({@link stirling.software.common.model.multipart.ByteArrayMultipartFile},
|
||||
* {@link stirling.software.common.model.multipart.FileUploadMultipartFile}) and pass it down
|
||||
* unchanged.
|
||||
*
|
||||
* <p>TODO: Migration required - longer term, the REST boundary should standardise on
|
||||
* {@code FileUpload}/{@code @RestForm} and this shim can be retired.
|
||||
*/
|
||||
public interface MultipartFile {
|
||||
|
||||
String getName();
|
||||
|
||||
String getOriginalFilename();
|
||||
|
||||
String getContentType();
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
long getSize();
|
||||
|
||||
byte[] getBytes() throws IOException;
|
||||
|
||||
InputStream getInputStream() throws IOException;
|
||||
|
||||
default void transferTo(File dest) throws IOException {
|
||||
transferTo(dest.toPath());
|
||||
}
|
||||
|
||||
default void transferTo(Path dest) throws IOException {
|
||||
try (InputStream in = getInputStream()) {
|
||||
Files.copy(in, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ package stirling.software.common.model.api;
|
||||
// consumed by controllers/services across the codebase; changing the type (e.g. to
|
||||
// byte[]/InputStream or jakarta.ws.rs form params) would ripple to every caller.
|
||||
// Keep the Spring type for now and rebind during the web-layer migration.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package stirling.software.common.model.api;
|
||||
// servlet/JAX-RS drop-in for a DTO field type. Changing this public field type to
|
||||
// byte[]/InputStream or a JAX-RS multipart type would ripple to all callers and the
|
||||
// API binding layer, so the type is kept until callers are migrated together.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package stirling.software.common.model.multipart;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
/**
|
||||
* In-memory {@link MultipartFile} backed by a byte array. Useful for tests and for code paths that
|
||||
* synthesize file content (migration shim - see {@link MultipartFile}).
|
||||
*/
|
||||
public class ByteArrayMultipartFile implements MultipartFile {
|
||||
|
||||
private final String name;
|
||||
private final String originalFilename;
|
||||
private final String contentType;
|
||||
private final byte[] content;
|
||||
|
||||
public ByteArrayMultipartFile(
|
||||
String name, String originalFilename, String contentType, byte[] content) {
|
||||
this.name = name;
|
||||
this.originalFilename = originalFilename;
|
||||
this.contentType = contentType;
|
||||
this.content = content != null ? content : new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return content.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return new ByteArrayInputStream(content);
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package stirling.software.common.model.multipart;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.jboss.resteasy.reactive.multipart.FileUpload;
|
||||
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
/**
|
||||
* Adapts a Quarkus REST {@link FileUpload} (the inbound multipart representation at the JAX-RS
|
||||
* boundary) to the {@link MultipartFile} migration shim, so controllers can pass uploads down to
|
||||
* the existing service layer without changing its method signatures.
|
||||
*/
|
||||
public class FileUploadMultipartFile implements MultipartFile {
|
||||
|
||||
private final FileUpload delegate;
|
||||
|
||||
public FileUploadMultipartFile(FileUpload delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/** Null-safe factory: returns null when the upload is absent. */
|
||||
public static MultipartFile of(FileUpload upload) {
|
||||
return upload == null ? null : new FileUploadMultipartFile(upload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return delegate.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return delegate.fileName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return delegate.contentType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return getSize() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return Files.readAllBytes(delegate.uploadedFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return Files.newInputStream(delegate.uploadedFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(Path dest) throws IOException {
|
||||
Files.copy(delegate.uploadedFile(), dest);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
// (controllers/other services) span the codebase; changing these public signatures to byte[]/
|
||||
// InputStream would ripple widely. The original import and type are kept intact pending a
|
||||
// coordinated migration of all callers.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
// JAX-RS/servlet drop-in. It is used as a public method return type and implemented by the
|
||||
// inner CustomMultipartFile class; converting the type would ripple to all callers. Keeping
|
||||
// the Spring type for now to preserve the public signature and behavior.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.springframework.core.io.Resource;
|
||||
// TODO: Migration required - org.springframework.web.multipart.MultipartFile is used in public
|
||||
// method signatures (storeFile, retrieveFile). No servlet/JAX-RS drop-in for utility method
|
||||
// params; changing it would ripple widely into callers. Keeping the type.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
// TODO: Migration required - org.springframework.web.servlet.mvc.method.annotation
|
||||
// .StreamingResponseBody is used in the public storeFromStreamingBody signature. No Quarkus/JAX-RS
|
||||
// drop-in; converting would ripple into callers. Keeping the type.
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.http.ResponseEntity;
|
||||
// TODO: Migration required - org.springframework.web.multipart.MultipartFile has no
|
||||
// JAX-RS drop-in for these utility method params; changing the type would ripple to
|
||||
// callers, so it is kept as-is for now.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
// TODO: Migration required - org.springframework.web.servlet.mvc.method.annotation
|
||||
// .StreamingResponseBody is a Spring MVC servlet type with no JAX-RS equivalent here;
|
||||
// it is consumed by FileStorage#storeFromStreamingBody and kept as-is for now.
|
||||
|
||||
@@ -18,7 +18,7 @@ import io.quarkus.scheduler.Scheduled;
|
||||
// drop-in. uploadFiles(...) is a public API consumed by callers and relies on isEmpty(),
|
||||
// getOriginalFilename(), getSize(), getContentType() and transferTo(Path). Changing it to
|
||||
// byte[]/InputStream would ripple to callers, so the Spring type is kept here intentionally.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
// MultipartFile and rely on isEmpty()/getOriginalFilename()/transferTo(File), which are
|
||||
// MultipartFile-specific. Converting the signatures (e.g. to byte[]/InputStream) would ripple
|
||||
// to all callers, so the type is intentionally kept until the calling endpoints are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import com.github.junrar.Archive;
|
||||
import com.github.junrar.exception.CorruptHeaderException;
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
// drop-in for these utility method parameters. The type appears in public method signatures
|
||||
// (convertCbzToPdf, isCbzFile, isComicBookFile) consumed by other modules; switching to
|
||||
// byte[]/InputStream would ripple across callers. Keep the Spring type until callers migrate.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
// drop-in for these utility method params. The public signatures of convertMultipartFileToFile and
|
||||
// multipartToFile are used by many callers, so the type is kept to avoid a wide ripple. Revisit to
|
||||
// accept InputStream/byte[] or a JAX-RS form-data type once callers are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import com.fathzer.soft.javaluator.DoubleEvaluator;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import javax.imageio.stream.ImageInputStream;
|
||||
// drop-in. loadImageWithExifOrientation(MultipartFile) is a public utility used by callers that
|
||||
// pass Spring MultipartFile; converting to byte[]/InputStream would change the public signature
|
||||
// and ripple to those callers. Keep the type until callers are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import com.drew.imaging.ImageMetadataReader;
|
||||
import com.drew.imaging.ImageProcessingException;
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter;
|
||||
import com.vladsch.flexmark.util.data.MutableDataSet;
|
||||
|
||||
@@ -47,7 +47,7 @@ import jakarta.ws.rs.core.MediaType;
|
||||
// MultipartFile implementation with a custom byte[]/InputStream holder and reworking the private
|
||||
// addAttachmentsToDocumentWithMapping signature. Kept as-is to preserve behavior; revisit to
|
||||
// introduce a Quarkus-friendly attachment abstraction.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
// (convertPdfToCbr/validatePdfFile/isPdfFile) consumed by callers; changing it to
|
||||
// byte[]/InputStream would ripple widely, so the type is intentionally kept until callers
|
||||
// are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
// JAX-RS drop-in for these public static utility method params. Converting to byte[]/
|
||||
// InputStream would change widely-used public signatures (convertPdfToCbz, isPdfFile,
|
||||
// validatePdfFile) and ripple to callers, so the type is kept until callers are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.apache.pdfbox.text.PDFTextStripper;
|
||||
// getOriginalFilename(), getInputStream() and ImageProcessingUtils.loadImageWithExifOrientation(file).
|
||||
// Changing the public signature would ripple across all callers, so the type is kept for now and
|
||||
// must be re-migrated together with its callers (e.g. to a JAX-RS multipart form / byte[] / InputStream).
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import jakarta.enterprise.context.ApplicationScoped;
|
||||
// TODO: Migration required - org.springframework.web.multipart.MultipartFile has no JAX-RS
|
||||
// drop-in. Kept to preserve the public convertMultipartFileToFile signature used by callers;
|
||||
// migrate to byte[]/InputStream or a Quarkus multipart type once callers are updated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.http.ResponseEntity;
|
||||
// drop-in for a utility method parameter. Converting multiPartFileToWebResponse to accept
|
||||
// byte[]/InputStream would ripple through every caller, so the Spring type and its import are kept
|
||||
// here intentionally.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ import org.springframework.core.io.InputStreamResource;
|
||||
// the superclass ctor ReplaceAndInvertColorStrategy(MultipartFile, ReplaceAndInvert) requires it.
|
||||
// No JAX-RS drop-in exists for this constructor param without rippling changes to the parent and
|
||||
// every caller, so the type is preserved here.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ import org.springframework.core.io.InputStreamResource;
|
||||
// the parent ReplaceAndInvertColorStrategy(MultipartFile, ReplaceAndInvert) constructor (not in
|
||||
// scope for this migration). There is no JAX-RS drop-in for this widely used public signature;
|
||||
// retained until the parent and its callers are migrated together.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import org.springframework.core.io.InputStreamResource;
|
||||
// for these constructor params. The parent class ReplaceAndInvertColorStrategy declares the same
|
||||
// MultipartFile constructor parameter; changing the public signature here would diverge from the
|
||||
// parent and ripple to callers, so the type is kept until the parent/callers are migrated.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import org.springframework.core.io.InputStreamResource;
|
||||
// the inherited PDFFile.setFileInput(MultipartFile) (PDFFile keeps this type for the same
|
||||
// reason); changing this constructor parameter would ripple to callers and the API binding
|
||||
// layer, so the type is kept until PDFFile and its callers are migrated together.
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import stirling.software.common.model.MultipartFile;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
Reference in New Issue
Block a user