com.adobe.platform.operation.internal.util.ValidationUtil Maven / Gradle / Ivy
/*
* Copyright 2019 Adobe
* All Rights Reserved.
*
* NOTICE: Adobe permits you to use, modify, and distribute this file in
* accordance with the terms of the Adobe license agreement accompanying
* it. If you have received this file from a source other than Adobe,
* then your use, modification, or distribution of it requires the prior
* written permission of Adobe.
*/
package com.adobe.platform.operation.internal.util;
import static java.lang.String.format;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import com.adobe.platform.operation.exception.SdkException;
import com.adobe.platform.operation.internal.ExtensionMediaTypeMapping;
import com.adobe.platform.operation.internal.InternalExecutionContext;
import com.adobe.platform.operation.internal.cpf.dto.request.platform.pagemanipulation.PageAction;
import com.adobe.platform.operation.internal.http.ByteArrayPart;
import com.adobe.platform.operation.internal.http.MultiPartRequest;
import com.adobe.platform.operation.internal.http.StringBodyPart;
import com.adobe.platform.operation.internal.options.CombineOperationInput;
import com.adobe.platform.operation.pdfops.options.PageRanges;
import com.adobe.platform.operation.pdfops.options.protectpdf.EncryptionAlgorithm;
import com.adobe.platform.operation.pdfops.options.protectpdf.PasswordProtectOptions;
import com.adobe.platform.operation.pdfops.options.protectpdf.ProtectPDFOptions;
public class ValidationUtil {
private static final long INPUT_FILE_SIZE_LIMIT = 104857600; // 100 MBs in bytes
private static final int USER_PASSWORD_MAX_LENGTH = 32;
private static final int USER_PASSWORD_MIN_LENGTH = 6;
private static final int PAGE_ACTIONS_MAX_LIMIT = 200;
private static final int AES_256_USER_PASSWORD_MAX_LENGTH = 127; // 127 UTF-8 bytes
private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
public static void validateMediaType(Set allowedMediaTypes, String mediaType) {
if (mediaType == null || !allowedMediaTypes.contains(mediaType)) {
throw new IllegalArgumentException("Operation cannot be performed on the specified input media type : " + mediaType);
}
}
public static void validateExecutionContext(InternalExecutionContext context) {
Objects.requireNonNull(context, "Client Context not initialized before invoking the operation");
if (context.getClientConfig() == null) {
throw new IllegalArgumentException("Client Context not initialized before invoking the operation");
}
context.validate();
}
public static void validateFileWithPageOptions(CombineOperationInput input,
Set allowedMimeTypes) {
validateMediaType(allowedMimeTypes, input.getSourceFileRef().getMediaType());
validatePageOptions(input);
}
private static void validatePageOptions(CombineOperationInput input) {
PageRanges pageRanges = input.getPageRanges();
if (pageRanges == null) {
throw new IllegalArgumentException("No page options provided for combining files PDFs");
}
pageRanges.validate();
}
public static void validateOptionInstanceType(Map mediaTypeOptionClassMap,
String sourceMediaType, Object options) {
Class instanceType = mediaTypeOptionClassMap.get(ExtensionMediaTypeMapping.getFromMimeType(sourceMediaType));
if (instanceType == null || !instanceType.isInstance(options)) {
throw new IllegalArgumentException(format("Invalid option instance type provided for source media type %s",
sourceMediaType));
}
}
/**
* A validation util which checks whether the given option instance is null or is instance of one of the given
* option classes from the provided set
*
* @param optionsClassSet a set of option classes
* @param options the option object to validate
*/
public static void validateOptionInstanceType(Set optionsClassSet, Object options) {
if (options == null || !optionsClassSet.contains(options.getClass())) {
throw new IllegalArgumentException("Invalid option instance type provided for the operation");
}
}
public static void validateOperationOptions(Object bean) {
Validator validator = validatorFactory.getValidator();
Set> violations = validator.validate(bean);
if (!violations.isEmpty()) {
String message = violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("; "));
throw new IllegalArgumentException(message);
}
}
public static void validateMultiPartBodySize(MultiPartRequest multiPartRequest) {
double totalSize = 0;
StringBodyPart stringBodyPart = multiPartRequest.getStringBodyPart();
List byteArrayParts = multiPartRequest.getByteArrayParts();
// Add the size(in bytes) of stringBodyPart
if (stringBodyPart != null && stringBodyPart.getBody() != null) {
totalSize = stringBodyPart.getBody().getBytes().length;
}
// Add the size(in bytes) for each byteArrayPart
if (byteArrayParts != null) {
for (ByteArrayPart byteArrayPart : byteArrayParts) {
totalSize += byteArrayPart.getBody().length;
}
}
// Compare the totalSize with INPUT_FILE_SIZE_LIMIT
if (totalSize > INPUT_FILE_SIZE_LIMIT) {
throw new SdkException("Total input file(s) size exceeds the acceptable limit");
}
}
private static void validateUserPassword(String userPassword, String encryptionAlgorithm) {
if (StringUtil.isNull(userPassword) || StringUtil.isEmpty(userPassword)) {
throw new IllegalArgumentException("User Password cannot be null or empty");
}
// User password validation for AES_128 encryption algorithm
if (encryptionAlgorithm.equals(EncryptionAlgorithm.AES_128.getValue())) {
if (!StandardCharsets.US_ASCII.newEncoder().canEncode(userPassword)) {
throw new IllegalArgumentException("User Password supports only ASCII characters for AES-128 encryption");
}
if (userPassword.length() < USER_PASSWORD_MIN_LENGTH) {
throw new IllegalArgumentException(format("User Password must be at least %d characters long for AES-128 encryption", USER_PASSWORD_MIN_LENGTH));
}
if (userPassword.length() > USER_PASSWORD_MAX_LENGTH) {
throw new IllegalArgumentException(format("User Password length cannot exceed %d characters for AES-128 encryption", USER_PASSWORD_MAX_LENGTH));
}
}
// User password validation for AES_256 encryption algorithm
else if (encryptionAlgorithm.equals(EncryptionAlgorithm.AES_256.getValue())) {
if (userPassword.getBytes(StandardCharsets.UTF_8).length > AES_256_USER_PASSWORD_MAX_LENGTH) {
throw new IllegalArgumentException(format("User Password length cannot exceed %d UTF-8 bytes for AES-256 encryption", AES_256_USER_PASSWORD_MAX_LENGTH));
}
}
}
public static void validateProtectPDFOptions(ProtectPDFOptions protectPDFOptions) {
// Validations for PasswordProtectOptions
if (PasswordProtectOptions.class.isInstance(protectPDFOptions)) {
PasswordProtectOptions passwordProtectOptions = (PasswordProtectOptions) protectPDFOptions;
// Validate encryption algo
if (passwordProtectOptions.getEncryptionAlgorithm() == null) {
throw new IllegalArgumentException("Encryption algorithm cannot be null");
}
// Validate user password
validateUserPassword(passwordProtectOptions.getUserPassword(), passwordProtectOptions.getEncryptionAlgorithm().getValue());
}
}
public static void validateInsertFilesInputs(Set supportedSourceMediaTypes, Map> filesToInsert) {
if (filesToInsert == null || filesToInsert.isEmpty()) {
throw new IllegalArgumentException("No files to insert in the base input file");
}
for (Map.Entry> entry : filesToInsert.entrySet()) {
if (entry.getKey() < 1) {
throw new IllegalArgumentException("Base file page should be greater than 0");
}
for (CombineOperationInput combineOperationInput : entry.getValue()) {
validateMediaType(supportedSourceMediaTypes, combineOperationInput.getSourceFileRef().getMediaType());
validatePageRanges(combineOperationInput.getPageRanges());
}
}
}
public static void validateReplaceFilesInputs(Set supportedSourceMediaTypes, Map filesToReplace) {
if (filesToReplace == null || filesToReplace.isEmpty()) {
throw new IllegalArgumentException("No files to replace with");
}
for (Map.Entry entry : filesToReplace.entrySet()) {
if (entry.getKey() < 1) {
throw new IllegalArgumentException("Base file page should be greater than 0");
}
validateMediaType(supportedSourceMediaTypes, entry.getValue().getSourceFileRef().getMediaType());
validatePageRanges(entry.getValue().getPageRanges());
}
}
public static void validatePageRanges(PageRanges pageRanges) {
if (pageRanges == null || pageRanges.isEmpty()) {
throw new IllegalArgumentException("No page ranges were set for the operation");
}
pageRanges.validate();
}
public static void validateRotatePageActions(List pageActions) {
if (pageActions.isEmpty()) {
throw new IllegalArgumentException("No rotation specified for the operation");
}
if (pageActions.size() > PAGE_ACTIONS_MAX_LIMIT) {
throw new IllegalArgumentException("Too many rotations not allowed.");
}
for (PageAction pageAction : pageActions) {
if (pageAction.getPageRanges().isEmpty()) {
throw new IllegalArgumentException("No page ranges were set for the operation");
}
}
}
}