@Override protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) { final boolean sslContextSet = validationContext.getProperty(SSL_CONTEXT).isSet(); if (sslContextSet) { final List<String> baseUrls = getBaseURLs(validationContext); final List<String> insecure = baseUrls.stream() .filter(url -> !url.startsWith("https")) .collect(Collectors.toList()); if (!insecure.isEmpty()) { return Collections.singleton(new ValidationResult.Builder() .subject(SCHEMA_REGISTRY_URLS.getDisplayName()) .input(insecure.get(0)) .valid(false) .explanation("When SSL Context is configured, all Schema Registry URL's must use HTTPS, not HTTP") .build()); } } return Collections.emptyList(); }
@Override protected Collection<ValidationResult> customValidate(ValidationContext validationContext) { Set<ValidationResult> results = new HashSet<>(); boolean strict = validationContext.getProperty(VALIDATE_FIELD_NAMES).asBoolean(); // Iterate over dynamic properties, validating the schemas, and adding results validationContext.getProperties().entrySet().stream().filter(entry -> entry.getKey().isDynamic()).forEach(entry -> { String subject = entry.getKey().getDisplayName(); String input = entry.getValue(); try { final Schema avroSchema = new Schema.Parser().setValidate(strict).parse(input); AvroTypeUtil.createSchema(avroSchema, input, SchemaIdentifier.EMPTY); } catch (final Exception e) { results.add(new ValidationResult.Builder() .input(input) .subject(subject) .valid(false) .explanation("Not a valid Avro Schema: " + e.getMessage()) .build()); } }); return results; }
@Override public Collection<ValidationResult> validate(ValidationContext validationContext) { final List<ValidationResult> validationResults = new ArrayList<>(); consumeConfigurations(validationContext.getAllProperties(), (clusterNamePatterns, patterns) -> {}, (entry, e) -> { final ValidationResult result = new ValidationResult.Builder() .subject(entry.getKey()) .input(entry.getValue()) .explanation(e.getMessage()) .valid(false) .build(); validationResults.add(result); }); return validationResults; }
@Override public ValidationResult validate(String subject, String uri, ValidationContext context) { String message = "not set"; boolean isValid = true; if (uri.trim().isEmpty()) { isValid = false; } else { final boolean elPresent = context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(uri); if (!elPresent) { try { new URIBuilder(URI.create(uri)).build(); } catch (RuntimeException e) { message = e.getMessage(); isValid = false; } } } return new ValidationResult.Builder() .subject(subject) .input(uri) .explanation("Dataset URI is invalid: " + message) .valid(isValid) .build(); } };
@Override public ValidationResult validate(final String subject, final String input, final ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { return new ValidationResult.Builder() .input(input) .subject(subject) .valid(true) .explanation("Expression Language is present") .build(); } try { new Schema.Parser().parse(input); return new ValidationResult.Builder() .valid(true) .build(); } catch (final Exception e) { return new ValidationResult.Builder() .input(input) .subject(subject) .valid(false) .explanation("Not a valid Avro Schema: " + e.getMessage()) .build(); } }
/** * Validates that one or more files exist, as specified in a single property. */ public static Validator createMultipleFilesExistValidator() { return (subject, input, context) -> { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build(); } final String[] files = input.split("\\s*,\\s*"); for (String filename : files) { try { final File file = new File(filename.trim()); final boolean valid = file.exists() && file.isFile(); if (!valid) { final String message = "File " + file + " does not exist or is not a file"; return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation(message).build(); } } catch (SecurityException e) { final String message = "Unable to access " + filename + " due to " + e.getMessage(); return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation(message).build(); } } return new ValidationResult.Builder().subject(subject).input(input).valid(true).build(); }; } }
@Override public ValidationResult validate(final String subject, final String input, final ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build(); } if (input == null) { return new ValidationResult.Builder() .subject(subject) .input(input) .valid(false) .explanation("Data Size cannot be null") .build(); } if (DATA_SIZE_PATTERN.matcher(input.toUpperCase()).matches()) { return new ValidationResult.Builder().subject(subject).input(input).valid(true).build(); } else { return new ValidationResult.Builder() .subject(subject).input(input) .valid(false) .explanation("Must be of format <Data Size> <Data Unit> where <Data Size>" + " is a non-negative integer and <Data Unit> is a supported Data" + " Unit, such as: B, KB, MB, GB, TB") .build(); } } };
/** * Reloads the script defined by the given string * * @param scriptBody the contents of the script to be loaded * @return true if the script was loaded successfully; false otherwise */ private boolean reloadScriptBody(final String scriptBody) { final Collection<ValidationResult> results = new HashSet<>(); try { return reloadScript(scriptBody); } catch (final Exception e) { final ComponentLog logger = getLogger(); final String message = "Unable to load script: " + e; logger.error(message, e); results.add(new ValidationResult.Builder() .subject("ScriptValidation") .valid(false) .explanation("Unable to load script due to " + e) .input(scriptingComponentHelper.getScriptPath()) .build()); } // store the updated validation results validationResults.set(results); // return whether there was any issues loading the configured script return results.isEmpty(); }
@Override protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) { final List<ValidationResult> results = new ArrayList<>(); if (validationContext.getProperty(MAX_BATCH_SIZE).asInteger() > 1 && validationContext.getProperty(PARSE_MESSAGES).asBoolean()) { results.add(new ValidationResult.Builder().subject("Parse Messages").input("true").valid(false) .explanation("Cannot set Parse Messages to 'true' if Batch Size is greater than 1").build()); } final String protocol = validationContext.getProperty(PROTOCOL).getValue(); final SSLContextService sslContextService = validationContext.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class); if (UDP_VALUE.getValue().equals(protocol) && sslContextService != null) { results.add(new ValidationResult.Builder() .explanation("SSL can not be used with UDP") .valid(false).subject("SSL Context").build()); } // Validate CLIENT_AUTH final String clientAuth = validationContext.getProperty(CLIENT_AUTH).getValue(); if (sslContextService != null && StringUtils.isBlank(clientAuth)) { results.add(new ValidationResult.Builder() .explanation("Client Auth must be provided when using TLS/SSL") .valid(false).subject("Client Auth").build()); } return results; }
@Override public ValidationResult validate(String subject, String input, ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { final AttributeExpression.ResultType resultType = context.newExpressionLanguageCompiler().getResultType(input); if (!resultType.equals(AttributeExpression.ResultType.STRING)) { return new ValidationResult.Builder() .subject(subject) .input(input) .valid(false) .explanation("Expected property to to return type " + AttributeExpression.ResultType.STRING + " but expression returns type " + resultType) .build(); } return new ValidationResult.Builder() .subject(subject) .input(input) .valid(true) .explanation("Property returns type " + AttributeExpression.ResultType.STRING) .build(); } return DPV_RE_VALIDATOR.validate(subject, input, context); } };
@Override protected Collection<ValidationResult> customValidate(ValidationContext validationContext) { final List<ValidationResult> problems = new ArrayList<>(); final String columns = validationContext.getProperty(COLUMNS).getValue(); final String filter = validationContext.getProperty(FILTER_EXPRESSION).getValue(); if (!StringUtils.isBlank(columns) && !StringUtils.isBlank(filter)) { problems.add(new ValidationResult.Builder() .subject(FILTER_EXPRESSION.getDisplayName()) .input(filter).valid(false) .explanation("A filter expression can not be used in conjunction with the Columns property") .build()); } String minTS = validationContext.getProperty(TIME_RANGE_MIN).getValue(); String maxTS = validationContext.getProperty(TIME_RANGE_MAX).getValue(); if ( (!StringUtils.isBlank(minTS) && StringUtils.isBlank(maxTS)) || (StringUtils.isBlank(minTS) && !StringUtils.isBlank(maxTS))){ problems.add(new ValidationResult.Builder() .subject(TIME_RANGE_MAX.getDisplayName()) .input(maxTS).valid(false) .explanation(String.format("%s and %s both should be either empty or provided", TIME_RANGE_MIN, TIME_RANGE_MAX)) .build()); } return problems; }
@Override public ValidationResult validate(String subject, String uri, ValidationContext context) { Configuration conf = getConfiguration(context.getProperty(CONF_XML_FILES).evaluateAttributeExpressions().getValue()); String error = null; if(StringUtils.isBlank(uri)) { return new ValidationResult.Builder().subject(subject).input(uri).explanation("Schema cannot be null.").valid(false).build(); } final boolean elPresent = context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(uri); if (!elPresent) { try { getSchema(uri, conf); } catch (SchemaNotFoundException e) { error = e.getMessage(); } } return new ValidationResult.Builder() .subject(subject) .input(uri) .explanation(error) .valid(error == null) .build(); } };
@Override protected Collection<ValidationResult> customValidate(ValidationContext context) { PropertyValue schemaProp = context.getProperty(SCHEMA); String schema = schemaProp.getValue(); String subject = SCHEMA.getName(); if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(schema)) { return Collections.singletonList(new ValidationResult.Builder().subject(subject).input(schema).explanation("Expression Language Present").valid(true).build()); } // If no Expression Language is present, try parsing the schema try { this.parseSchema(schema); } catch (Exception e) { final List<ValidationResult> problems = new ArrayList<>(1); problems.add(new ValidationResult.Builder().subject(subject) .input(schema) .valid(false) .explanation("Error while parsing the schema: " + e.getMessage()) .build()); return problems; } return super.customValidate(context); }
@Override public ValidationResult validate(final String subject, final String input, final ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build(); } if (input == null) { return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation("Time Period cannot be null").build(); } if (TIME_DURATION_PATTERN.matcher(input.toLowerCase()).matches()) { return new ValidationResult.Builder().subject(subject).input(input).valid(true).build(); } else { return new ValidationResult.Builder() .subject(subject) .input(input) .valid(false) .explanation("Must be of format <duration> <TimeUnit> where <duration> is a " + "non-negative integer and TimeUnit is a supported Time Unit, such " + "as: nanos, millis, secs, mins, hrs, days") .build(); } } };
@Override public ValidationResult validate(final String subject, final String input, final ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build(); } if (input == null) { return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation("Time Period cannot be null").build(); } if (TIME_DURATION_PATTERN.matcher(input.toLowerCase()).matches() || input.equals("-1")) { return new ValidationResult.Builder().subject(subject).input(input).valid(true).build(); } else { return new ValidationResult.Builder() .subject(subject) .input(input) .valid(false) .explanation("Must be of format <duration> <TimeUnit> where <duration> is a " + "non-negative integer and TimeUnit is a supported Time Unit, such " + "as: nanos, millis, secs, mins, hrs, days") .build(); } } };
@Override protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) { ArrayList<ValidationResult> results = new ArrayList<>(super.customValidate(validationContext)); // validate the grok expression against configuration GrokCompiler grokCompiler = GrokCompiler.newInstance(); String subject = GROK_EXPRESSION.getName(); String input = validationContext.getProperty(GROK_EXPRESSION).getValue(); GrokExpressionValidator validator; try (final InputStream in = getClass().getResourceAsStream(DEFAULT_PATTERN_NAME); final Reader reader = new InputStreamReader(in)) { grokCompiler.register(reader); } catch (IOException e) { results.add(new ValidationResult.Builder() .input(input) .subject(subject) .valid(false) .explanation("Unable to load default patterns: " + e.getMessage()) .build()); } validator = new GrokExpressionValidator(validationContext.getProperty(PATTERN_FILE).getValue(),grokCompiler); results.add(validator.validate(subject,input,validationContext)); return results; }
@Override public List<ValidationResult> customValidate(ValidationContext validationContext) { final List<ValidationResult> results = new ArrayList<>(super.customValidate(validationContext)); final String chosenQUERY_PARSER = validationContext.getProperty(QUERY_PARSER).getValue(); if (!chosenQUERY_PARSER.equals(NONE.getValue()) && !validationContext.getProperty(QUERY_PARSER_INPUT).isSet() ) { results.add(new ValidationResult.Builder().input("QUERY_PARSER_INPUT") .subject(QUERY_PARSER.getDisplayName()) .explanation("Split and Regex parsers require a valid Regular Expression") .valid(false) .build()); } if (chosenQUERY_PARSER.equals(NONE.getValue()) && validationContext.getProperty(QUERY_PARSER_INPUT).isSet()) { results.add(new ValidationResult.Builder().input("QUERY_PARSER") .subject(QUERY_PARSER_INPUT.getDisplayName()) .explanation("NONE parser does not support the use of Regular Expressions. " + "Please select another parser or delete the regular expression entered in this field.") .valid(false) .build()); } return results; }
@Override public ValidationResult validate(final String subject, final String value, final ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(value)) { return new ValidationResult.Builder().subject(subject) .input(value) .explanation("Expression Language Present").valid(true) .build(); } String reason = ""; if (!AVRO_FIELDNAME_PATTERN.matcher(subject).matches()) { reason = subject + " is not a valid Avro fieldname"; } if (!AVRO_FIELDNAME_PATTERN.matcher(value).matches()) { reason = reason + value + " is not a valid Avro fieldname"; } return new ValidationResult.Builder().subject(subject).input(value) .explanation(reason).valid(reason.equals("")).build(); } };
@Override public ValidationResult validate(String subject, String input, ValidationContext context) { if (context.isExpressionLanguageSupported(subject) && context.isExpressionLanguagePresent(input)) { return new ValidationResult.Builder().subject(subject).input(input).explanation("Expression Language Present").valid(true).build(); } final String[] files = input.split(","); for (String filename : files) { try { final File file = new File(filename.trim()); final boolean valid = file.exists() && file.isFile(); if (!valid) { final String message = "File " + file + " does not exist or is not a file"; return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation(message).build(); } } catch (SecurityException e) { final String message = "Unable to access " + filename + " due to " + e.getMessage(); return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation(message).build(); } } return new ValidationResult.Builder().subject(subject).input(input).valid(true).build(); }
@Override public ValidationResult validate(final String subject, final String input, final ValidationContext context) { final String value = context.newPropertyValue(input).evaluateAttributeExpressions().getValue(); try { SiteToSiteRestApiClient.parseClusterUrls(value); return new ValidationResult.Builder() .input(input) .subject(subject) .valid(true) .build(); } catch (IllegalArgumentException ex) { return new ValidationResult.Builder() .input(input) .subject(subject) .valid(false) .explanation(ex.getLocalizedMessage()) .build(); } } }