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

com.atlassian.bamboo.specs.api.validators.common.ValidationUtils Maven / Gradle / Ivy

There is a newer version: 10.2.3-m01
Show newest version
package com.atlassian.bamboo.specs.api.validators.common;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static com.atlassian.bamboo.specs.api.validators.common.DbConstraintUtils.checkLength;

/**
 * Various utility methods for validating data of Bamboo Specs.
 * 

* Validation methods from this class prefixed with {@code validate} return validation problems and do not * throw any exception. For helper methods which throw exceptions on validation failures, use * {@link ImporterUtils}. */ public final class ValidationUtils { private ValidationUtils() { } //doesn't contain system variables public static boolean containsBambooVariable(@Nullable String value) { return value != null && value.contains("${bamboo"); } public static boolean repositoryUriContainsPassword(final URI repositoryUri) { return StringUtils.contains(repositoryUri.getRawUserInfo(), ":"); } public static Optional validateRequired(@NotNull ValidationContext validationContext, @Nullable Object value) { if (value == null) { return Optional.of(new ValidationProblem(validationContext, "must be defined")); } else { return Optional.empty(); } } public static Optional validateRequiredString(@NotNull ValidationContext validationContext, @Nullable String value) { return validateRequiredString(validationContext, value, false); } public static Optional validateRequiredString(@NotNull ValidationContext validationContext, @Nullable String value, boolean requireNonBlank) { if (value == null) { return Optional.of(new ValidationProblem(validationContext, "must be defined")); } else if (requireNonBlank ? StringUtils.isBlank(value) : StringUtils.isEmpty(value)) { return Optional.of(new ValidationProblem(validationContext, "can not be empty")); } else { return Optional.empty(); } } public static Optional validateBoolean(@NotNull ValidationContext validationContext, @Nullable String value) { if (value != null && BooleanUtils.toBooleanObject(value) == null) { return Optional.of(new ValidationProblem(validationContext, "must be boolean value but is '%s'", value)); } else { return Optional.empty(); } } public static Optional validateRequiredBoolean(@NotNull ValidationContext validationContext, @Nullable String value) { if (value == null) { return Optional.of(new ValidationProblem(validationContext, "must be defined")); } return validateBoolean(validationContext, value); } public static Optional validateLong(@NotNull ValidationContext validationContext, @Nullable String value) { if (value == null) { return Optional.empty(); } if (!NumberUtils.isNumber(value)) { return Optional.of(new ValidationProblem(validationContext, "must be numerical long value but is '%s'", value)); } try { Long.parseLong(value); } catch (NumberFormatException e) { return Optional.of(new ValidationProblem(validationContext, "must be numerical long value but is '%s'", value)); } return Optional.empty(); } public static Optional validateRequiredLong(@NotNull ValidationContext validationContext, @Nullable String value) { if (value == null) { return Optional.of(new ValidationProblem(validationContext, "must be defined")); } return validateLong(validationContext, value); } public static > Optional validateEnum(@NotNull ValidationContext validationContext, @Nullable String value, @NotNull Class enumClass) { if (value == null) { return Optional.empty(); } if (!EnumUtils.isValidEnum(enumClass, value)) { return Optional.of(new ValidationProblem(validationContext, "must be enum value of %s but is '%s'", ArrayUtils.toString(enumClass.getEnumConstants(), "{}"), value)); } else { return Optional.empty(); } } public static > Optional validateRequiredEnum(@NotNull ValidationContext validationContext, @Nullable String value, @NotNull Class enumClass) { if (value == null) { return Optional.of(new ValidationProblem(validationContext, "must be defined")); } return validateEnum(validationContext, value, enumClass); } public static Optional validatePositive(@NotNull ValidationContext validationContext, long value) { if (value < 0) { return Optional.of(new ValidationProblem(validationContext, "must be >= 0 but is %d", value)); } else { return Optional.empty(); } } public static Optional validatePositive(@NotNull ValidationContext validationContext, int value) { if (value < 0) { return Optional.of(new ValidationProblem(validationContext, "must be >= 0 but is %d", value)); } else { return Optional.empty(); } } public static Optional validateUrl(@NotNull ValidationContext validationContext, @Nullable String urlString, @NotNull Set supportedSchemes) { if (urlString == null) { return Optional.empty(); } try { final URI uri = new URI(urlString); final String scheme = uri.getScheme(); if (!supportedSchemes.contains(uri.getScheme())) { return Optional.of(new ValidationProblem(validationContext, "scheme '%s' is not supported - supported schemes are: %s", scheme, String.join(", ", supportedSchemes))); } } catch (URISyntaxException e) { //windows network share or possibly scp format //scp format is not usual uri (for example [email protected]:atlassian/bamboo-docker-plugin.git) //we do best effort accepting everything that doesn't contain "://" if (urlString.startsWith("\\\\") || !urlString.contains("://")) { return Optional.empty(); } return Optional.of(new ValidationProblem(validationContext, String.format("Malformed URL: %s", urlString))); } return Optional.empty(); } public static Optional validateNotContainsXssRelatedCharacters(@NotNull ValidationContext validationContext, @Nullable String value) { if (BambooStringUtils.containsXssRelatedCharacters(value)) { return Optional.of(new ValidationProblem(validationContext, "can not contain any of those characters: %s but it is '%s'", Arrays.toString(BambooStringUtils.XSS_RELATED_CHARACTERS), value)); } return Optional.empty(); } public static Optional validateNotContainsRelaxedXssRelatedCharacters(@NotNull ValidationContext validationContext, @Nullable String value) { if (BambooStringUtils.containsRelaxedXssRelatedCharacters(value)) { return Optional.of(new ValidationProblem(validationContext, "can not contain any of those characters: %s but it is '%s'", Arrays.toString(BambooStringUtils.RELAXED_XSS_RELATED_CHARACTERS), value)); } return Optional.empty(); } public static Optional validateNotContainsShellInjectionRelatedCharacters(@NotNull ValidationContext validationContext, @Nullable String value) { if (BambooStringUtils.containsShellInjectionRelatedCharacters(value)) { return Optional.of( new ValidationProblem(validationContext, "can not contain any of those characters: %s, nor this substring: '%s' but it is '%s'", Arrays.toString(BambooStringUtils.SHELL_INJECTION_RELATED_CHARACTERS), BambooStringUtils.SHELL_INJECTION_DOLLAR_PARENTHESIS, value)); } return Optional.empty(); } @NotNull public static List validateName(@NotNull ValidationContext validationContext, @Nullable String name) { return validateName(validationContext, name, true); } @NotNull public static List validateName(@NotNull ValidationContext validationContext, @Nullable String name, boolean required) { final ValidationContext validationContextWithName = validationContext.with("Name"); final List errors = new ArrayList<>(); if (required) { validateRequiredString(validationContextWithName, name, true) .ifPresent(errors::add); } checkLength(validationContextWithName, name, DbConstraintUtils.DATABASE_STRING_LIMIT, "it can not be longer than " + DbConstraintUtils.DATABASE_STRING_LIMIT + " characters but has " + StringUtils.length(name)) .ifPresent(errors::add); validateNotContainsXssRelatedCharacters(validationContextWithName, name) .ifPresent(errors::add); return errors; } @NotNull public static List validateDescription(@NotNull ValidationContext validationContext, @Nullable String description) { final ValidationContext validationContextWithDescription = validationContext.with("Description"); final List errors = new ArrayList<>(); validateNotContainsXssRelatedCharacters(validationContextWithDescription, description) .ifPresent(errors::add); return errors; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy