/** * Copyright (c) 2009 - 2016 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.util; import org.xnap.commons.i18n.I18n; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * The PropertyValidator class provides a simple framework for determining whether or not a given * value is valid for a specified property. The abstraction of this logic allows the logic to be * reused for multiple classes of property (i.e. attributes, facts, etc.). */ public abstract class PropertyValidator { /** * Mini-class for performing validation of a class of values */ protected abstract static class Validator { protected I18n i18n; protected String propertyType; public Validator(I18n i18n, String propertyType) { if (i18n == null) { throw new IllegalArgumentException("i18n is null"); } if (propertyType == null) { throw new IllegalArgumentException("propertyType is null"); } this.i18n = i18n; this.propertyType = propertyType; } public abstract void validate(String key, String value); } /** * Validator verifying the key or value are small enough to fit in the database */ protected static class LengthValidator extends Validator { private int length; public LengthValidator(I18n i18n, String propertyType, int length) { super(i18n, propertyType); if (length < 0) { throw new IllegalArgumentException("length is a non-positive value"); } this.length = length; } public void validate(String key, String value) { if (key.length() > this.length) { throw new PropertyValidationException(this.i18n.tr( "The {0} name \"{1}\" must not exceed {2} characters in length", this.propertyType, key, this.length )); } if (value != null && value.length() > this.length) { throw new PropertyValidationException(this.i18n.tr( "The value for {0} \"{1}\" must not exceed {2} characters in length", this.propertyType, key, this.length )); } } } /** * Validator providing validation for integer properties */ protected static class IntegerValidator extends Validator { public IntegerValidator(I18n i18n, String propertyType) { super(i18n, propertyType); } public void validate(String key, String value) { try { Integer.parseInt(value); } catch (NumberFormatException nfe) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be an integer value", this.propertyType, key)); } } } /** * Validator providing validation for non-negative properties */ protected static class NonNegativeIntegerValidator extends Validator { public NonNegativeIntegerValidator(I18n i18n, String propertyType) { super(i18n, propertyType); } public void validate(String key, String value) { try { int parsed = Integer.parseInt(value); if (parsed < 0) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be a positive, integer value", this.propertyType, key)); } } catch (NumberFormatException nfe) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be a positive, integer value", this.propertyType, key)); } } } /** * Validator providing validation for long-integer properties */ protected static class LongValidator extends Validator { public LongValidator(I18n i18n, String propertyType) { super(i18n, propertyType); } public void validate(String key, String value) { try { Long.parseLong(value); } catch (NumberFormatException nfe) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be a long-integer value", this.propertyType, key)); } } } /** * Validator providing validation for non-negative, long-integer properties */ protected static class NonNegativeLongValidator extends Validator { public NonNegativeLongValidator(I18n i18n, String propertyType) { super(i18n, propertyType); } public void validate(String key, String value) { try { long parsed = Long.parseLong(value); if (parsed < 0) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be a positive, long-integer value", this.propertyType, key)); } } catch (NumberFormatException nfe) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be a positive, long-integer value", this.propertyType, key)); } } } /** * Validator providing validation for Boolean properties */ protected static class BooleanValidator extends Validator { private static final Set<String> BOOLEAN_VALUES = Collections.unmodifiableSet(new HashSet<String>( Arrays.asList("true", "false", "1", "0") )); public BooleanValidator(I18n i18n, String propertyType) { super(i18n, propertyType); } public void validate(String key, String value) { if (!(BOOLEAN_VALUES.contains(value.trim().toLowerCase()))) { throw new PropertyValidationException(this.i18n.tr( "The {0} \"{1}\" must be a Boolean value", this.propertyType, key)); } } } protected Map<String, Validator> validators; protected Set<Validator> globalValidators; /** * Creates a new PropertyValidator instance. */ public PropertyValidator() { this.validators = new HashMap<String, Validator>(); this.globalValidators = new HashSet<Validator>(); // Validators will be added by subclasses as necessary } /** * Checks whether the value given for the specified key is valid. * * @param key * The key (property name) to validate * * @param value * The value to validate * * @throws IllegalArgumentException * if key is null * * #throws PropertyValidationException * if the given property has an illegal value */ // TODO: Fix the Javadoc above once we can workaround/fix the checkstyle issue that prevents // it from finding the PropertyValidationException. public void validate(String key, String value) { if (key == null) { throw new IllegalArgumentException("key is null"); } for (Validator validator : this.globalValidators) { if (validator != null) { validator.validate(key, value); } } if (value != null && !value.isEmpty()) { Validator validator = this.validators.get(key); if (validator != null) { validator.validate(key, value); } } } }