diff --git a/nifi-api/src/main/java/org/apache/nifi/processor/util/StandardValidators.java b/nifi-api/src/main/java/org/apache/nifi/processor/util/StandardValidators.java index 136c67d57f8a..0980069538ff 100644 --- a/nifi-api/src/main/java/org/apache/nifi/processor/util/StandardValidators.java +++ b/nifi-api/src/main/java/org/apache/nifi/processor/util/StandardValidators.java @@ -23,7 +23,7 @@ import org.apache.nifi.expression.AttributeExpression.ResultType; import org.apache.nifi.flowfile.FlowFile; import org.apache.nifi.processor.DataUnit; -import org.apache.nifi.time.TimeFormat; +import org.apache.nifi.time.DurationFormat; import java.io.File; import java.net.URI; @@ -391,10 +391,8 @@ public ValidationResult validate(final String subject, final String input, final } return new ValidationResult.Builder().input(input).subject(subject).valid(true).build(); }; - /** - * URL Validator that does not allow the Expression Language to be used - */ - public static final Validator URL_VALIDATOR = createURLValidator(); + + public static final Validator URL_VALIDATOR = new URLValidator(); public static final Validator URI_VALIDATOR = new Validator() { @Override @@ -463,7 +461,7 @@ private static boolean isEmpty(final String value) { } public static final Validator TIME_PERIOD_VALIDATOR = new Validator() { - private final Pattern TIME_DURATION_PATTERN = Pattern.compile(TimeFormat.TIME_DURATION_REGEX); + private final Pattern TIME_DURATION_PATTERN = Pattern.compile(DurationFormat.TIME_DURATION_REGEX); @Override public ValidationResult validate(final String subject, final String input, final ValidationContext context) { @@ -531,27 +529,6 @@ public static Validator createDirectoryExistsValidator(final boolean allowExpres return new DirectoryExistsValidator(allowExpressionLanguage, createDirectoryIfMissing); } - private static Validator createURLValidator() { - return new Validator() { - @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(); - } - - try { - // Check that we can parse the value as a URL - final String evaluatedInput = context.newPropertyValue(input).evaluateAttributeExpressions().getValue(); - URI.create(evaluatedInput).toURL(); - return new ValidationResult.Builder().subject(subject).input(input).explanation("Valid URL").valid(true).build(); - } catch (final Exception e) { - return new ValidationResult.Builder().subject(subject).input(input).explanation("Not a valid URL").valid(false).build(); - } - } - }; - } - - public static Validator createListValidator(boolean trimEntries, boolean excludeEmptyEntries, Validator elementValidator) { return createListValidator(trimEntries, excludeEmptyEntries, elementValidator, false); @@ -815,7 +792,7 @@ public ValidationResult validate(final String subject, final String input, final // // static class TimePeriodValidator implements Validator { - private static final Pattern pattern = Pattern.compile(TimeFormat.TIME_DURATION_REGEX); + private static final Pattern pattern = Pattern.compile(DurationFormat.TIME_DURATION_REGEX); private final long minNanos; private final long maxNanos; @@ -843,7 +820,7 @@ public ValidationResult validate(final String subject, final String input, final final boolean validSyntax = pattern.matcher(lowerCase).matches(); final ValidationResult.Builder builder = new ValidationResult.Builder(); if (validSyntax) { - final long nanos = new TimeFormat().getTimeDuration(lowerCase, TimeUnit.NANOSECONDS); + final long nanos = DurationFormat.getTimeDuration(lowerCase, TimeUnit.NANOSECONDS); if (nanos < minNanos || nanos > maxNanos) { builder.subject(subject).input(input).valid(false) diff --git a/nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/UriUtils.java b/nifi-api/src/main/java/org/apache/nifi/processor/util/URLValidator.java similarity index 58% rename from nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/UriUtils.java rename to nifi-api/src/main/java/org/apache/nifi/processor/util/URLValidator.java index 13808d927386..95d532224876 100644 --- a/nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/UriUtils.java +++ b/nifi-api/src/main/java/org/apache/nifi/processor/util/URLValidator.java @@ -14,20 +14,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.nifi.util; +package org.apache.nifi.processor.util; + +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.components.Validator; + +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; +public class URLValidator implements Validator { -/** - * Utility class providing java.net.URI utilities. - * The regular expressions in this class used to capture the various components of a URI were adapted from - * UriComponentsBuilder - */ -public class UriUtils { private static final String SCHEME_PATTERN = "([^:/?#]+):"; private static final String USERINFO_PATTERN = "([^@\\[/?#]*)"; private static final String HOST_IPV4_PATTERN = "[^\\[/?#:]*"; @@ -40,10 +42,25 @@ public class UriUtils { // Regex patterns that matches URIs. See RFC 3986, appendix B private static final Pattern URI_PATTERN = Pattern.compile( - "^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + - ")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?"); + "^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + + ")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?"); - private UriUtils() {} + + @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(); + } + + try { + // Check that we can parse the value as a URL + final String evaluatedInput = context.newPropertyValue(input).evaluateAttributeExpressions().getValue(); + createURL(evaluatedInput); + return new ValidationResult.Builder().subject(subject).input(input).explanation("Valid URL").valid(true).build(); + } catch (final Exception e) { + return new ValidationResult.Builder().subject(subject).input(input).explanation("Not a valid URL").valid(false).build(); + } + } /** * This method provides an alternative to the use of java.net.URI's single argument constructor and 'create' method. @@ -56,12 +73,12 @@ private UriUtils() {} * On the other hand, java.net.URI's seven argument constructor provides these quoting capabilities. In order * to take advantage of this constructor, this method parses the given string into the arguments needed * thereby allowing for instantiating a java.net.URI with the quoting of all illegal characters. - * @param uri String representing a URI. - * @return Instance of java.net.URI - * @throws URISyntaxException Thrown on parsing failures + * @param url String representing a URL. + * @return Instance of java.net.URL + * @throws MalformedURLException if unable to create a URL from the given String representation */ - public static URI create(String uri) throws URISyntaxException { - final Matcher matcher = URI_PATTERN.matcher(uri); + public static URL createURL(final String url) throws MalformedURLException { + final Matcher matcher = URI_PATTERN.matcher(url); if (matcher.matches()) { final String scheme = matcher.group(2); final String userInfo = matcher.group(5); @@ -70,9 +87,14 @@ public static URI create(String uri) throws URISyntaxException { final String path = matcher.group(9); final String query = matcher.group(11); final String fragment = matcher.group(13); - return new URI(scheme, userInfo, host, port != null ? Integer.parseInt(port) : -1, path, query, fragment); + + try { + return new URI(scheme, userInfo, host, port != null ? Integer.parseInt(port) : -1, path, query, fragment).toURL(); + } catch (final URISyntaxException e) { + throw new MalformedURLException("Unable to create URL from " + url + ": " + e.getMessage()); + } } else { - throw new IllegalArgumentException(uri + " is not a valid URI"); + throw new MalformedURLException(url + " is not a valid URL"); } } } diff --git a/nifi-api/src/main/java/org/apache/nifi/time/TimeFormat.java b/nifi-api/src/main/java/org/apache/nifi/time/DurationFormat.java similarity index 85% rename from nifi-api/src/main/java/org/apache/nifi/time/TimeFormat.java rename to nifi-api/src/main/java/org/apache/nifi/time/DurationFormat.java index 2682ed17c0e7..6de336a36c03 100644 --- a/nifi-api/src/main/java/org/apache/nifi/time/TimeFormat.java +++ b/nifi-api/src/main/java/org/apache/nifi/time/DurationFormat.java @@ -23,24 +23,26 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class TimeFormat { +public class DurationFormat { private static final String UNION = "|"; // for Time Durations - private static final String NANOS = join(UNION, "ns", "nano", "nanos", "nanosecond", "nanoseconds"); - private static final String MILLIS = join(UNION, "ms", "milli", "millis", "millisecond", "milliseconds"); - private static final String SECS = join(UNION, "s", "sec", "secs", "second", "seconds"); - private static final String MINS = join(UNION, "m", "min", "mins", "minute", "minutes"); - private static final String HOURS = join(UNION, "h", "hr", "hrs", "hour", "hours"); - private static final String DAYS = join(UNION, "d", "day", "days"); - private static final String WEEKS = join(UNION, "w", "wk", "wks", "week", "weeks"); - - private static final String VALID_TIME_UNITS = join(UNION, NANOS, MILLIS, SECS, MINS, HOURS, DAYS, WEEKS); + private static final String NANOS = String.join(UNION, "ns", "nano", "nanos", "nanosecond", "nanoseconds"); + private static final String MILLIS = String.join(UNION, "ms", "milli", "millis", "millisecond", "milliseconds"); + private static final String SECS = String.join(UNION, "s", "sec", "secs", "second", "seconds"); + private static final String MINS = String.join(UNION, "m", "min", "mins", "minute", "minutes"); + private static final String HOURS = String.join(UNION, "h", "hr", "hrs", "hour", "hours"); + private static final String DAYS = String.join(UNION, "d", "day", "days"); + private static final String WEEKS = String.join(UNION, "w", "wk", "wks", "week", "weeks"); + + private static final String VALID_TIME_UNITS = String.join(UNION, NANOS, MILLIS, SECS, MINS, HOURS, DAYS, WEEKS); public static final String TIME_DURATION_REGEX = "([\\d.]+)\\s*(" + VALID_TIME_UNITS + ")"; public static final Pattern TIME_DURATION_PATTERN = Pattern.compile(TIME_DURATION_REGEX); private static final List TIME_UNIT_MULTIPLIERS = Arrays.asList(1000L, 1000L, 1000L, 60L, 60L, 24L); + private DurationFormat() { + } /** * Returns a time duration in the requested {@link TimeUnit} after parsing the {@code String} @@ -53,7 +55,7 @@ public class TimeFormat { * @return the whole number value of this duration in the requested units * @see #getPreciseTimeDuration(String, TimeUnit) */ - public long getTimeDuration(final String value, final TimeUnit desiredUnit) { + public static long getTimeDuration(final String value, final TimeUnit desiredUnit) { return Math.round(getPreciseTimeDuration(value, desiredUnit)); } @@ -81,7 +83,7 @@ public long getTimeDuration(final String value, final TimeUnit desiredUnit) { * @param desiredUnit the desired output {@link TimeUnit} * @return the parsed and converted amount (without a unit) */ - public double getPreciseTimeDuration(final String value, final TimeUnit desiredUnit) { + public static double getPreciseTimeDuration(final String value, final TimeUnit desiredUnit) { final Matcher matcher = TIME_DURATION_PATTERN.matcher(value.toLowerCase()); if (!matcher.matches()) { throw new IllegalArgumentException("Value '" + value + "' is not a valid time duration"); @@ -134,7 +136,7 @@ public double getPreciseTimeDuration(final String value, final TimeUnit desiredU * @param timeUnit the current time unit * @return the time duration as a whole number ({@code long}) and the smaller time unit used */ - List makeWholeNumberTime(double decimal, TimeUnit timeUnit) { + static List makeWholeNumberTime(double decimal, TimeUnit timeUnit) { // If the value is already a whole number, return it and the current time unit if (decimal == Math.rint(decimal)) { final long rounded = Math.round(decimal); @@ -168,7 +170,7 @@ List makeWholeNumberTime(double decimal, TimeUnit timeUnit) { * @param newTimeUnit the destination time unit * @return the numerical multiplier between the units */ - long calculateMultiplier(TimeUnit originalTimeUnit, TimeUnit newTimeUnit) { + static long calculateMultiplier(TimeUnit originalTimeUnit, TimeUnit newTimeUnit) { if (originalTimeUnit == newTimeUnit) { return 1; } else if (originalTimeUnit.ordinal() < newTimeUnit.ordinal()) { @@ -190,7 +192,7 @@ long calculateMultiplier(TimeUnit originalTimeUnit, TimeUnit newTimeUnit) { * @param originalUnit the TimeUnit * @return the next smaller TimeUnit */ - TimeUnit getSmallerTimeUnit(TimeUnit originalUnit) { + static TimeUnit getSmallerTimeUnit(TimeUnit originalUnit) { if (originalUnit == null || TimeUnit.NANOSECONDS == originalUnit) { throw new IllegalArgumentException("Cannot determine a smaller time unit than '" + originalUnit + "'"); } else { @@ -204,7 +206,7 @@ TimeUnit getSmallerTimeUnit(TimeUnit originalUnit) { * @param rawUnit the String containing the desired unit * @return true if the unit is "weeks"; false otherwise */ - private boolean isWeek(final String rawUnit) { + private static boolean isWeek(final String rawUnit) { return switch (rawUnit) { case "w", "wk", "wks", "week", "weeks" -> true; default -> false; @@ -219,7 +221,7 @@ private boolean isWeek(final String rawUnit) { * @param rawUnit the String to parse * @return the TimeUnit */ - protected TimeUnit determineTimeUnit(String rawUnit) { + protected static TimeUnit determineTimeUnit(String rawUnit) { return switch (rawUnit.toLowerCase()) { case "ns", "nano", "nanos", "nanoseconds" -> TimeUnit.NANOSECONDS; case "µs", "micro", "micros", "microseconds" -> TimeUnit.MICROSECONDS; @@ -231,21 +233,4 @@ protected TimeUnit determineTimeUnit(String rawUnit) { default -> throw new IllegalArgumentException("Could not parse '" + rawUnit + "' to TimeUnit"); }; } - - private static String join(final String delimiter, final String... values) { - if (values.length == 0) { - return ""; - } else if (values.length == 1) { - return values[0]; - } - - final StringBuilder sb = new StringBuilder(); - sb.append(values[0]); - for (int i = 1; i < values.length; i++) { - sb.append(delimiter).append(values[i]); - } - - return sb.toString(); - } - } diff --git a/nifi-api/src/test/java/org/apache/nifi/time/TestTimeFormat.java b/nifi-api/src/test/java/org/apache/nifi/time/TestTimeFormat.java index 697e07daa947..d2bcdcc70fc3 100644 --- a/nifi-api/src/test/java/org/apache/nifi/time/TestTimeFormat.java +++ b/nifi-api/src/test/java/org/apache/nifi/time/TestTimeFormat.java @@ -38,7 +38,7 @@ public class TestTimeFormat { @ParameterizedTest @MethodSource("getParse") public void testParse(String value, TimeUnit desiredUnit, Long expected) { - assertEquals(expected, new TimeFormat().getTimeDuration(value, desiredUnit)); + assertEquals(expected, DurationFormat.getTimeDuration(value, desiredUnit)); } private static Stream getParse() { @@ -54,7 +54,7 @@ private static Stream getParse() { @ParameterizedTest @ValueSource(strings = {"1 week", "1 wk", "1 w", "1 wks", "1 weeks"}) public void testGetTimeDurationShouldConvertWeeks(String week) { - assertEquals(7L, new TimeFormat().getTimeDuration(week, TimeUnit.DAYS)); + assertEquals(7L, DurationFormat.getTimeDuration(week, TimeUnit.DAYS)); } @@ -62,7 +62,7 @@ public void testGetTimeDurationShouldConvertWeeks(String week) { @ValueSource(strings = {"-1 week", "-1 wk", "-1 w", "-1 weeks", "- 1 week"}) public void testGetTimeDurationShouldHandleNegativeWeeks(String week) { IllegalArgumentException iae = - assertThrows(IllegalArgumentException.class, () -> new TimeFormat().getTimeDuration(week, TimeUnit.DAYS)); + assertThrows(IllegalArgumentException.class, () -> DurationFormat.getTimeDuration(week, TimeUnit.DAYS)); assertTrue(iae.getMessage().contains("Value '" + week + "' is not a valid time duration")); } @@ -71,34 +71,34 @@ public void testGetTimeDurationShouldHandleNegativeWeeks(String week) { @ValueSource(strings = {"1 work", "1 wek", "1 k"}) public void testGetTimeDurationShouldHandleInvalidAbbreviations(String week) { IllegalArgumentException iae = - assertThrows(IllegalArgumentException.class, () -> new TimeFormat().getTimeDuration(week, TimeUnit.DAYS)); + assertThrows(IllegalArgumentException.class, () -> DurationFormat.getTimeDuration(week, TimeUnit.DAYS)); assertTrue(iae.getMessage().contains("Value '" + week + "' is not a valid time duration")); } @ParameterizedTest @ValueSource(strings={"1week", "1wk", "1w", "1wks", "1weeks"}) public void testGetTimeDurationShouldHandleNoSpaceInInput(String week) { - assertEquals(7L, new TimeFormat().getTimeDuration(week, TimeUnit.DAYS)); + assertEquals(7L, DurationFormat.getTimeDuration(week, TimeUnit.DAYS)); } @ParameterizedTest @ValueSource(strings={"10 ms", "10 millis", "10 milliseconds"}) public void testGetTimeDurationWithWholeNumbers(String whole){ - assertEquals(10L, new TimeFormat().getTimeDuration(whole, TimeUnit.MILLISECONDS)); + assertEquals(10L, DurationFormat.getTimeDuration(whole, TimeUnit.MILLISECONDS)); } @ParameterizedTest @ValueSource(strings={"0.010 s", "0.010 seconds"}) public void testGetTimeDurationWithDecimalNumbers(String decimal){ - assertEquals(10L, new TimeFormat().getTimeDuration(decimal, TimeUnit.MILLISECONDS)); + assertEquals(10L, DurationFormat.getTimeDuration(decimal, TimeUnit.MILLISECONDS)); } @ParameterizedTest @MethodSource("getOneWeekInOtherUnits") public void testGetPreciseTimeDurationShouldHandleWeeks(TimeUnit timeUnit, long expected){ - assertEquals(expected, new TimeFormat().getPreciseTimeDuration("1 week", timeUnit)); + assertEquals(expected, DurationFormat.getPreciseTimeDuration("1 week", timeUnit)); } private static Stream getOneWeekInOtherUnits() { @@ -115,7 +115,7 @@ private static Stream getOneWeekInOtherUnits() { @ParameterizedTest @MethodSource("getOneAndAHalfWeeksInOtherUnits") public void testGetPreciseTimeDurationShouldHandleDecimalWeeks(TimeUnit timeUnit, double expected) { - assertEquals(expected, new TimeFormat().getPreciseTimeDuration("1.5 week", timeUnit)); + assertEquals(expected, DurationFormat.getPreciseTimeDuration("1.5 week", timeUnit)); } private static Stream getOneAndAHalfWeeksInOtherUnits() { @@ -131,19 +131,19 @@ private static Stream getOneAndAHalfWeeksInOtherUnits() { @ParameterizedTest @ValueSource(strings={"10 ms", "10 millis", "10 milliseconds"}) public void testGetPreciseTimeDurationWithWholeNumbers(String whole) { - assertEquals(10.0, new TimeFormat().getPreciseTimeDuration(whole, TimeUnit.MILLISECONDS)); + assertEquals(10.0, DurationFormat.getPreciseTimeDuration(whole, TimeUnit.MILLISECONDS)); } @ParameterizedTest @ValueSource(strings={"0.010 s", "0.010 seconds"}) public void testGetPreciseTimeDurationWithDecimalNumbers(String decimal) { - assertEquals(10.0, new TimeFormat().getPreciseTimeDuration(decimal, TimeUnit.MILLISECONDS)); + assertEquals(10.0, DurationFormat.getPreciseTimeDuration(decimal, TimeUnit.MILLISECONDS)); } @ParameterizedTest @MethodSource("getTinyDecimalValues") public void testGetPreciseTimeDurationShouldHandleSmallDecimalValues(String originalValue, TimeUnit desiredUnit, double expectedValue) { - assertEquals(expectedValue, new TimeFormat().getPreciseTimeDuration(originalValue, desiredUnit)); + assertEquals(expectedValue, DurationFormat.getPreciseTimeDuration(originalValue, desiredUnit)); } private static Stream getTinyDecimalValues() { @@ -156,14 +156,14 @@ private static Stream getTinyDecimalValues() { @ParameterizedTest @EnumSource(TimeUnit.class) public void testMakeWholeNumberTimeShouldHandleWholeNumbers(TimeUnit timeUnit) { - assertEquals(Arrays.asList(10L, timeUnit), new TimeFormat().makeWholeNumberTime(10.0, timeUnit)); + assertEquals(Arrays.asList(10L, timeUnit), DurationFormat.makeWholeNumberTime(10.0, timeUnit)); } @ParameterizedTest @MethodSource("getNanoSecondsForMakeWholeNumber") public void testMakeWholeNumberTimeShouldHandleNanoseconds(double original, long expected) { assertEquals(Arrays.asList(expected, TimeUnit.NANOSECONDS), - new TimeFormat().makeWholeNumberTime(original, TimeUnit.NANOSECONDS)); + DurationFormat.makeWholeNumberTime(original, TimeUnit.NANOSECONDS)); } private static Stream getNanoSecondsForMakeWholeNumber() { @@ -177,7 +177,7 @@ private static Stream getNanoSecondsForMakeWholeNumber() { @NullSource public void testGetSmallerTimeUnitWithNull(TimeUnit timeUnit) { IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, - () -> new TimeFormat().getSmallerTimeUnit(timeUnit)); + () -> DurationFormat.getSmallerTimeUnit(timeUnit)); assertEquals("Cannot determine a smaller time unit than 'null'", iae.getMessage()); } @@ -185,7 +185,7 @@ public void testGetSmallerTimeUnitWithNull(TimeUnit timeUnit) { @Test public void testGetSmallerTimeUnitWithNanoseconds() { IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, - () -> new TimeFormat().getSmallerTimeUnit(TimeUnit.NANOSECONDS)); + () -> DurationFormat.getSmallerTimeUnit(TimeUnit.NANOSECONDS)); assertEquals("Cannot determine a smaller time unit than 'NANOSECONDS'", iae.getMessage()); } @@ -193,7 +193,7 @@ public void testGetSmallerTimeUnitWithNanoseconds() { @ParameterizedTest @MethodSource("getSmallerUnits") public void testShouldGetSmallerTimeUnit(TimeUnit original, TimeUnit expected) { - assertEquals(expected, new TimeFormat().getSmallerTimeUnit(original)); + assertEquals(expected, DurationFormat.getSmallerTimeUnit(original)); } private static Stream getSmallerUnits() { @@ -208,7 +208,7 @@ private static Stream getSmallerUnits() { @ParameterizedTest @MethodSource("getMultipliers") void testShouldCalculateMultiplier(TimeUnit original, TimeUnit newTimeUnit, long expected) { - assertEquals(expected, new TimeFormat().calculateMultiplier(original, newTimeUnit)); + assertEquals(expected, DurationFormat.calculateMultiplier(original, newTimeUnit)); } private static Stream getMultipliers() { @@ -224,7 +224,7 @@ private static Stream getMultipliers() { @MethodSource("getIncorrectUnits") public void testCalculateMultiplierShouldHandleIncorrectUnits(TimeUnit original, TimeUnit newTimeUnit) { IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, - () -> new TimeFormat().calculateMultiplier(original, newTimeUnit)); + () -> DurationFormat.calculateMultiplier(original, newTimeUnit)); assertTrue(iae.getMessage().matches("The original time unit '.*' must be larger than the new time unit '.*'")); } @@ -238,14 +238,14 @@ private static Stream getIncorrectUnits() { @ParameterizedTest @MethodSource("getDecimalsForMakeWholeNumber") public void testMakeWholeNumberTimeShouldHandleDecimals(double decimal, TimeUnit timeUnit) { - assertEquals(Arrays.asList(10L, TimeUnit.NANOSECONDS), new TimeFormat().makeWholeNumberTime(decimal, timeUnit)); + assertEquals(Arrays.asList(10L, TimeUnit.NANOSECONDS), DurationFormat.makeWholeNumberTime(decimal, timeUnit)); } @ParameterizedTest @MethodSource("getDecimalsForMetricConversions") public void testMakeWholeNumberTimeShouldHandleMetricConversions(double originalValue, TimeUnit originalUnits, long expectedValue, TimeUnit expectedUnits) { assertEquals(Arrays.asList(expectedValue, expectedUnits), - new TimeFormat().makeWholeNumberTime(originalValue, originalUnits)); + DurationFormat.makeWholeNumberTime(originalValue, originalUnits)); } private static Stream getDecimalsForMetricConversions() { @@ -260,7 +260,7 @@ private static Stream getDecimalsForMetricConversions() { @MethodSource("getDecimalsForNonMetricConversions") public void testMakeWholeNumberTimeShouldHandleNonMetricConversions(double originalValue, TimeUnit originalUnits, long expectedValue, TimeUnit expectedUnits) { assertEquals(Arrays.asList(expectedValue, expectedUnits), - new TimeFormat().makeWholeNumberTime(originalValue, originalUnits)); + DurationFormat.makeWholeNumberTime(originalValue, originalUnits)); } private static Stream getDecimalsForNonMetricConversions() { diff --git a/nifi-commons/nifi-utils/src/test/java/org/apache/nifi/util/TestUriUtils.java b/nifi-api/src/test/java/org/apache/nifi/util/TestURLValidator.java similarity index 78% rename from nifi-commons/nifi-utils/src/test/java/org/apache/nifi/util/TestUriUtils.java rename to nifi-api/src/test/java/org/apache/nifi/util/TestURLValidator.java index b38a8eda7f83..38cbd940a341 100644 --- a/nifi-commons/nifi-utils/src/test/java/org/apache/nifi/util/TestUriUtils.java +++ b/nifi-api/src/test/java/org/apache/nifi/util/TestURLValidator.java @@ -14,26 +14,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.nifi.util; +import org.apache.nifi.processor.util.URLValidator; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.function.Executable; -import java.net.URISyntaxException; +import java.net.MalformedURLException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; -public class TestUriUtils { +public class TestURLValidator { + @Test void testValidUri() { - final String uri = "https://en.wikipedia.org/w/api.php?action=query&list=recentchanges&format=json&rcprop=user|comment|parsedcomment|timestamp|title|sizes|tags"; - assertDoesNotThrow((Executable) () -> UriUtils.create(uri)); + final String url = "https://en.wikipedia.org/w/api.php?action=query&list=recentchanges&format=json&rcprop=user|comment|parsedcomment|timestamp|title|sizes|tags"; + assertDoesNotThrow(() -> URLValidator.createURL(url)); } @Test void testInvalidUri() { final String uri = "http:// _"; - assertThrows(URISyntaxException.class, () -> UriUtils.create(uri)); + assertThrows(MalformedURLException.class, () -> URLValidator.createURL(uri)); } + } diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPropertyValue.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPropertyValue.java index 33788bb62832..3366ed87bec8 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPropertyValue.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPropertyValue.java @@ -31,7 +31,7 @@ import org.apache.nifi.parameter.ParameterLookup; import org.apache.nifi.processor.DataUnit; import org.apache.nifi.processor.exception.ProcessException; -import org.apache.nifi.time.TimeFormat; +import org.apache.nifi.time.DurationFormat; import java.time.Duration; import java.util.Map; @@ -110,7 +110,7 @@ public Double asDouble() { @Override public Long asTimePeriod(final TimeUnit timeUnit) { - return (rawValue == null) ? null : new TimeFormat().getTimeDuration(rawValue.trim(), timeUnit); + return (rawValue == null) ? null : DurationFormat.getTimeDuration(rawValue.trim(), timeUnit); } @Override diff --git a/nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/FormatUtils.java b/nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/FormatUtils.java index c9bd5a730e8c..27022c731b91 100644 --- a/nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/FormatUtils.java +++ b/nifi-commons/nifi-utils/src/main/java/org/apache/nifi/util/FormatUtils.java @@ -17,7 +17,7 @@ package org.apache.nifi.util; import org.apache.nifi.processor.DataUnit; -import org.apache.nifi.time.TimeFormat; +import org.apache.nifi.time.DurationFormat; import java.text.NumberFormat; import java.time.Instant; @@ -35,8 +35,8 @@ public class FormatUtils { // 'public static final' members defined for backward compatibility, since they were moved to TimeFormat. - public static final String TIME_DURATION_REGEX = TimeFormat.TIME_DURATION_REGEX; - public static final Pattern TIME_DURATION_PATTERN = TimeFormat.TIME_DURATION_PATTERN; + public static final String TIME_DURATION_REGEX = DurationFormat.TIME_DURATION_REGEX; + public static final Pattern TIME_DURATION_PATTERN = DurationFormat.TIME_DURATION_PATTERN; private static final LocalDate EPOCH_INITIAL_DATE = LocalDate.of(1970, 1, 1); @@ -149,7 +149,7 @@ public static String formatDataSize(final double dataSize) { * @see #getPreciseTimeDuration(String, TimeUnit) */ public static long getTimeDuration(final String value, final TimeUnit desiredUnit) { - return new TimeFormat().getTimeDuration(value, desiredUnit); + return DurationFormat.getTimeDuration(value, desiredUnit); } /** @@ -177,7 +177,7 @@ public static long getTimeDuration(final String value, final TimeUnit desiredUni * @return the parsed and converted amount (without a unit) */ public static double getPreciseTimeDuration(final String value, final TimeUnit desiredUnit) { - return new TimeFormat().getPreciseTimeDuration(value, desiredUnit); + return DurationFormat.getPreciseTimeDuration(value, desiredUnit); } public static String formatUtilization(final double utilization) { diff --git a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/data/explorer/StandardKustoQueryService.java b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/data/explorer/StandardKustoQueryService.java index 05f639da8e3e..c904243fb832 100644 --- a/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/data/explorer/StandardKustoQueryService.java +++ b/nifi-nar-bundles/nifi-azure-bundle/nifi-azure-processors/src/main/java/org/apache/nifi/services/azure/data/explorer/StandardKustoQueryService.java @@ -19,7 +19,6 @@ import com.microsoft.azure.kusto.data.ClientFactory; import com.microsoft.azure.kusto.data.StreamingClient; import com.microsoft.azure.kusto.data.auth.ConnectionStringBuilder; - import org.apache.commons.lang3.tuple.Pair; import org.apache.nifi.annotation.documentation.CapabilityDescription; import org.apache.nifi.annotation.documentation.Tags; diff --git a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/services/slack/SlackRecordSink.java b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/services/slack/SlackRecordSink.java index f833122cec45..f99cf56647f8 100644 --- a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/services/slack/SlackRecordSink.java +++ b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/services/slack/SlackRecordSink.java @@ -56,7 +56,6 @@ public class SlackRecordSink extends AbstractControllerService implements Record " It only needs to be changed if Slack changes its API URL.") .required(true) .defaultValue(SLACK_API_URL) - .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) .addValidator(StandardValidators.URL_VALIDATOR) .build(); diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java index 1c477d319bb4..7822d4d543d8 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java @@ -71,6 +71,7 @@ import org.apache.nifi.processor.Relationship; import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.processor.util.StandardValidators; +import org.apache.nifi.processor.util.URLValidator; import org.apache.nifi.processors.standard.http.ContentEncodingStrategy; import org.apache.nifi.processors.standard.http.CookieStrategy; import org.apache.nifi.processors.standard.http.FlowFileNamingStrategy; @@ -85,7 +86,6 @@ import org.apache.nifi.security.util.TlsException; import org.apache.nifi.ssl.SSLContextService; import org.apache.nifi.stream.io.StreamUtils; -import org.apache.nifi.util.UriUtils; import javax.annotation.Nullable; import javax.net.ssl.SSLContext; @@ -98,7 +98,6 @@ import java.net.CookiePolicy; import java.net.Proxy; import java.net.Proxy.Type; -import java.net.URI; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -853,8 +852,7 @@ public void onTrigger(ProcessContext context, ProcessSession session) throws Pro FlowFile responseFlowFile = null; try { final String urlProperty = trimToEmpty(context.getProperty(HTTP_URL).evaluateAttributeExpressions(requestFlowFile).getValue()); - final URI uri = UriUtils.create(urlProperty); - final URL url = uri.toURL(); + final URL url = URLValidator.createURL(urlProperty); Request httpRequest = configureRequest(context, session, requestFlowFile, url); logRequest(logger, httpRequest);