Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.nifi.components.resource.ResourceType;
import org.apache.nifi.dbcp.ConnectionUrlValidator;
import org.apache.nifi.dbcp.DBCPValidator;
import org.apache.nifi.dbcp.DriverClassValidator;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.kerberos.KerberosUserService;
import org.apache.nifi.processor.util.StandardValidators;
Expand Down Expand Up @@ -67,7 +68,7 @@ private DBCPProperties() {
.description("Database driver class name")
.defaultValue(null)
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.addValidator(new DriverClassValidator())
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,11 @@ static class JndiJmsProviderUrlValidator implements Validator {
public ValidationResult validate(final String subject, final String input, final ValidationContext context) {
final ValidationResult.Builder builder = new ValidationResult.Builder().subject(subject).input(input);

if (input == null || input.isEmpty()) {
final String url = context.newPropertyValue(input).evaluateAttributeExpressions().getValue();
if (url == null || url.isEmpty()) {
builder.valid(false);
builder.explanation("URL is required");
} else if (isUrlAllowed(input)) {
} else if (isUrlAllowed(url)) {
builder.valid(true);
builder.explanation("URL scheme allowed");
} else {
Expand All @@ -176,7 +177,8 @@ public ValidationResult validate(final String subject, final String input, final
private boolean isUrlAllowed(final String input) {
final boolean allowed;

final Matcher matcher = URL_SCHEME_PATTERN.matcher(input);
final String normalizedUrl = input.trim();
final Matcher matcher = URL_SCHEME_PATTERN.matcher(normalizedUrl);
if (matcher.matches()) {
final String scheme = matcher.group(SCHEME_GROUP);
allowed = isSchemeAllowed(scheme);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public class JndiJmsConnectionFactoryProviderTest {

private static final String LDAP_PROVIDER_URL = "ldap://127.0.0.1";

private static final String LDAP_PROVIDER_URL_SPACED = String.format(" %s", LDAP_PROVIDER_URL);

private static final String LDAP_PROVIDER_URL_EXPRESSION = "ldap:${separator}//127.0.0.1";

private static final String HOST_PORT_URL = "127.0.0.1:1024";

private static final String LDAP_ALLOWED_URL_SCHEMES = "ldap";
Expand Down Expand Up @@ -81,6 +85,24 @@ void testPropertiesInvalidUrlScheme() {
runner.assertNotValid(provider);
}

@Test
void testPropertiesInvalidUrlSchemeSpaced() {
setFactoryProperties();

runner.setProperty(provider, JndiJmsConnectionFactoryProperties.JNDI_PROVIDER_URL, LDAP_PROVIDER_URL_SPACED);

runner.assertNotValid(provider);
}

@Test
void testPropertiesInvalidUrlSchemeExpression() {
setFactoryProperties();

runner.setProperty(provider, JndiJmsConnectionFactoryProperties.JNDI_PROVIDER_URL, LDAP_PROVIDER_URL_EXPRESSION);

runner.assertNotValid(provider);
}

@Test
void testPropertiesHostPortUrl() {
setFactoryProperties();
Expand All @@ -90,7 +112,6 @@ void testPropertiesHostPortUrl() {
runner.assertValid(provider);
}


@Test
void testUrlSchemeValidSystemProperty() {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ public ValidationResult validate(final String subject, final String input, final
builder.valid(false);
builder.explanation("Connection URL required");
} else {
final String url = context.newPropertyValue(input).evaluateAttributeExpressions().getValue();
final String url = context.newPropertyValue(input).evaluateAttributeExpressions().getValue().trim();

if (isUrlUnsupported(url)) {
builder.valid(false);
builder.explanation(String.format("Connection URL starts with an unsupported scheme %s", UNSUPPORTED_SCHEMES));
builder.explanation(String.format("Connection URL contains an unsupported scheme %s", UNSUPPORTED_SCHEMES));
} else {
builder.valid(true);
builder.explanation("Connection URL is valid");
Expand All @@ -55,7 +55,7 @@ private boolean isUrlUnsupported(final String url) {
boolean unsupported = false;

for (final String unsupportedScheme : UNSUPPORTED_SCHEMES) {
if (url.startsWith(unsupportedScheme)) {
if (url.contains(unsupportedScheme)) {
unsupported = true;
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.dbcp;

import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.components.Validator;

import java.util.Collections;
import java.util.Set;

/**
* Database Driver Class Validator supports system attribute expressions and evaluates class names against unsupported values
*/
public class DriverClassValidator implements Validator {
private static final Set<String> UNSUPPORTED_CLASSES = Collections.singleton("org.h2.Driver");

@Override
public ValidationResult validate(final String subject, final String input, final ValidationContext context) {
final ValidationResult.Builder builder = new ValidationResult.Builder().subject(subject).input(input);

if (input == null || input.isEmpty()) {
builder.valid(false);
builder.explanation("Driver Class required");
} else {
final String driverClass = context.newPropertyValue(input).evaluateAttributeExpressions().getValue().trim();

if (isDriverClassUnsupported(driverClass)) {
builder.valid(false);
builder.explanation(String.format("Driver Class is listed as unsupported %s", UNSUPPORTED_CLASSES));
} else {
builder.valid(true);
builder.explanation("Driver Class is valid");
}
}

return builder.build();
}

private boolean isDriverClassUnsupported(final String driverClass) {
return UNSUPPORTED_CLASSES.contains(driverClass);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ class ConnectionUrlValidatorTest {

private static final String UNSUPPORTED_URL = "jdbc:h2:file";

private static final String UNSUPPORTED_URL_SPACED = String.format(" %s ", UNSUPPORTED_URL);

private static final String UNSUPPORTED_URL_EXPRESSION = String.format("${attribute}%s", UNSUPPORTED_URL);

private static final String VENDOR_URL = "jdbc:vendor";

private ValidationContext validationContext;
Expand Down Expand Up @@ -67,6 +71,22 @@ void testValidateUnsupportedUrl() {
assertFalse(result.isValid());
}

@Test
void testValidateUnsupportedUrlExpressionLanguage() {
final ValidationResult result = validator.validate(SUBJECT, UNSUPPORTED_URL_EXPRESSION, validationContext);

assertNotNull(result);
assertFalse(result.isValid());
}

@Test
void testValidateUnsupportedUrlSpaced() {
final ValidationResult result = validator.validate(SUBJECT, UNSUPPORTED_URL_SPACED, validationContext);

assertNotNull(result);
assertFalse(result.isValid());
}

@Test
void testValidateSupportedUrl() {
final ValidationResult result = validator.validate(SUBJECT, VENDOR_URL, validationContext);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.dbcp;

import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.util.MockProcessContext;
import org.apache.nifi.util.MockValidationContext;
import org.apache.nifi.util.NoOpProcessor;
import org.apache.nifi.util.TestRunners;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

class DriverClassValidatorTest {

private static final String SUBJECT = "Database Driver Class";

private static final String EMPTY = "";

private static final String UNSUPPORTED_DRIVER = "org.h2.Driver";

private static final String UNSUPPORTED_DRIVER_SPACED = String.format(" %s ", UNSUPPORTED_DRIVER);

private static final String UNSUPPORTED_DRIVER_EXPRESSION = String.format("${attribute}%s", UNSUPPORTED_DRIVER);

private static final String OTHER_DRIVER = "org.apache.nifi.Driver";

private ValidationContext validationContext;

private DriverClassValidator validator;

@BeforeEach
void setValidator() {
validator = new DriverClassValidator();

final MockProcessContext processContext = (MockProcessContext) TestRunners.newTestRunner(NoOpProcessor.class).getProcessContext();
validationContext = new MockValidationContext(processContext);
}

@Test
void testValidateEmpty() {
final ValidationResult result = validator.validate(SUBJECT, EMPTY, validationContext);

assertNotNull(result);
assertFalse(result.isValid());
}

@Test
void testValidateUnsupportedDriver() {
final ValidationResult result = validator.validate(SUBJECT, UNSUPPORTED_DRIVER, validationContext);

assertNotNull(result);
assertFalse(result.isValid());
}

@Test
void testValidateUnsupportedDriverExpressionLanguage() {
final ValidationResult result = validator.validate(SUBJECT, UNSUPPORTED_DRIVER_EXPRESSION, validationContext);

assertNotNull(result);
assertFalse(result.isValid());
}

@Test
void testValidateUnsupportedDriverSpaced() {
final ValidationResult result = validator.validate(SUBJECT, UNSUPPORTED_DRIVER_SPACED, validationContext);

assertNotNull(result);
assertFalse(result.isValid());
}

@Test
void testValidateSupportedDriver() {
final ValidationResult result = validator.validate(SUBJECT, OTHER_DRIVER, validationContext);

assertNotNull(result);
assertTrue(result.isValid());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public class HikariCPConnectionPool extends AbstractControllerService implements
.description("The fully-qualified class name of the JDBC driver. Example: com.mysql.jdbc.Driver")
.defaultValue(null)
.required(true)
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.addValidator(new DriverClassValidator())
.expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
.build();

Expand Down