This is an automated email from the ASF dual-hosted git repository.
ramanathan1504 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/main by this push:
new a47b2b1f7f [main] Add `@Required` and validation to
`StringMatchFilter` `text` attribute (#3158 port) (#4153)
a47b2b1f7f is described below
commit a47b2b1f7fcf0468a92693cdc081c92b97d81873
Author: Vasily Pelikh <[email protected]>
AuthorDate: Fri Aug 21 18:21:37 2026 +0300
[main] Add `@Required` and validation to `StringMatchFilter` `text`
attribute (#3158 port) (#4153)
* Update StringMatchFilter builder API (#3509)
* Guard against NPEs
* added private constructor to builder
* added getText() accessor
* add JVerify nullability annotations
* added detailed javadoc with implementation details
* optimized AbstractLifeCycle and AbstractFilter "equalsImpl"
implementations
Signed-off-by: Vasily Pelikh <[email protected]>
Co-authored-by: Jeff Thomas <[email protected]>
Co-authored-by: Ramanathan <[email protected]>
---
.../log4j/core/filter/StringMatchFilterTest.java | 126 +++++++++++++++++++++
.../log4j2-stringmatchfilter-3153-nok.xml | 23 ++++
.../resources/log4j2-stringmatchfilter-3153-ok.xml | 23 ++++
.../log4j/core/filter/StringMatchFilter.java | 53 +++++++--
4 files changed, 214 insertions(+), 11 deletions(-)
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StringMatchFilterTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StringMatchFilterTest.java
new file mode 100644
index 0000000000..09864f285b
--- /dev/null
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/StringMatchFilterTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.logging.log4j.core.filter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
+import org.apache.logging.log4j.test.ListStatusListener;
+import org.apache.logging.log4j.test.junit.UsingStatusListener;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Unit tests for {@link StringMatchFilter}.
+ */
+@UsingStatusListener
+class StringMatchFilterTest {
+
+ /**
+ * Test the normal valid programmatic instantiation of a {@link
StringMatchFilter} via its builder.
+ */
+ @Test
+ void testFilterBuilderOK() {
+ StringMatchFilter.Builder stringMatchFilterBuilder =
StringMatchFilter.newBuilder();
+ stringMatchFilterBuilder.setText("foo");
+ StringMatchFilter stringMatchFilter = stringMatchFilterBuilder.build();
+ assertNotNull(stringMatchFilter, "The filter should not be null.");
+ assertEquals("foo", stringMatchFilter.getText());
+ }
+
+ /**
+ * Test that if no match-string is set on the builder, the '{@link
StringMatchFilter.Builder#build()}' returns
+ * {@code null}.
+ */
+ @Test
+ void testFilterBuilderFailsWithNullText() {
+ StringMatchFilter.Builder stringMatchFilterBuilder =
StringMatchFilter.newBuilder();
+ Assertions.assertNull(stringMatchFilterBuilder.build());
+ }
+
+ /**
+ * Test that if a {@code null} string is set as a match-pattern, a {@link
NullPointerException} is thrown.
+ */
+ @Test
+ @SuppressWarnings({"DataFlowIssue" // invalid null parameter explicitly
being tested
+ })
+ void testFilterBuilderFailsWithExceptionOnNullText() {
+ StringMatchFilter.Builder stringMatchFilterBuilder =
StringMatchFilter.newBuilder();
+ Assertions.assertThrows(NullPointerException.class, () ->
stringMatchFilterBuilder.setText(null));
+ }
+
+ /**
+ * Test that if an empty ({@code ""}) string is set as a match-pattern, an
{@code IllegalArgumentException} is thrown.
+ */
+ @Test
+ void testFilterBuilderFailsWithExceptionOnEmptyText() {
+ StringMatchFilter.Builder stringMatchFilterBuilder =
StringMatchFilter.newBuilder();
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
stringMatchFilterBuilder.setText(""));
+ }
+
+ /**
+ * Test the deprecated {@link
StringMatchFilter.Builder#setMatchString(String)} alias still works as expected.
+ */
+ @Test
+ void testFilterBuilderWithDeprecatedSetMatchString() {
+ StringMatchFilter.Builder stringMatchFilterBuilder =
StringMatchFilter.newBuilder();
+ stringMatchFilterBuilder.setMatchString("foo");
+ StringMatchFilter stringMatchFilter = stringMatchFilterBuilder.build();
+ assertNotNull(stringMatchFilter, "The filter should not be null.");
+ assertEquals("foo", stringMatchFilter.getText());
+ }
+
+ /**
+ * Test that if a {@link StringMatchFilter} is specified with a 'text'
attribute it is correctly instantiated.
+ *
+ * @param configuration the configuration
+ */
+ @Test
+ @LoggerContextSource("log4j2-stringmatchfilter-3153-ok.xml")
+ void testConfigurationWithTextPOS(final Configuration configuration) {
+ final Filter filter = configuration.getFilter();
+ assertNotNull(filter, "The filter should not be null.");
+ assertInstanceOf(
+ StringMatchFilter.class, filter, "Expected a
StringMatchFilter, but got: " + filter.getClass());
+ assertEquals("FooBar", ((StringMatchFilter) filter).getText());
+ }
+
+ /**
+ * Test that if a {@link StringMatchFilter} is specified without a 'text'
attribute it is not instantiated and the
+ * {@code @Required} constraint validation reports an error.
+ *
+ * @param configuration the configuration
+ * @param listener the status listener capturing the validation errors
+ */
+ @Test
+ @LoggerContextSource("log4j2-stringmatchfilter-3153-nok.xml")
+ void testConfigurationWithTextNEG(final Configuration configuration, final
ListStatusListener listener) {
+ final Filter filter = configuration.getFilter();
+ assertNull(filter, "The filter should be null.");
+ assertThat(listener.findStatusData(Level.ERROR)).anyMatch(statusData
-> statusData
+ .getMessage()
+ .getFormattedMessage()
+ .contains("No text provided for StringMatchFilter"));
+ }
+}
diff --git
a/log4j-core-test/src/test/resources/log4j2-stringmatchfilter-3153-nok.xml
b/log4j-core-test/src/test/resources/log4j2-stringmatchfilter-3153-nok.xml
new file mode 100644
index 0000000000..ff7a83ce8c
--- /dev/null
+++ b/log4j-core-test/src/test/resources/log4j2-stringmatchfilter-3153-nok.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<Configuration status="warn">
+ <StringMatchFilter/> <!-- no 'text' attribute: an unconfigurable filter
must not be created -->
+ <Loggers>
+ <Root/> <!-- one logger to avoid test warning about no defined loggers
-->
+ </Loggers>
+</Configuration>
diff --git
a/log4j-core-test/src/test/resources/log4j2-stringmatchfilter-3153-ok.xml
b/log4j-core-test/src/test/resources/log4j2-stringmatchfilter-3153-ok.xml
new file mode 100644
index 0000000000..598dfaa302
--- /dev/null
+++ b/log4j-core-test/src/test/resources/log4j2-stringmatchfilter-3153-ok.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<Configuration status="warn">
+ <StringMatchFilter text="FooBar"/>
+ <Loggers>
+ <Root/> <!-- one logger to avoid test warning about no defined loggers
-->
+ </Loggers>
+</Configuration>
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StringMatchFilter.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StringMatchFilter.java
index 51ee3b2a20..d30a2a64eb 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StringMatchFilter.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/StringMatchFilter.java
@@ -16,6 +16,7 @@
*/
package org.apache.logging.log4j.core.filter;
+import java.util.Objects;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.Filter;
@@ -26,7 +27,10 @@ import org.apache.logging.log4j.plugins.Configurable;
import org.apache.logging.log4j.plugins.Plugin;
import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
import org.apache.logging.log4j.plugins.PluginFactory;
+import org.apache.logging.log4j.plugins.util.Assert;
+import org.apache.logging.log4j.plugins.validation.constraints.Required;
import org.apache.logging.log4j.util.PerformanceSensitive;
+import org.jspecify.annotations.NonNull;
/**
* This filter returns the onMatch result if the message in the event matches
the specified text
@@ -38,11 +42,22 @@ import org.apache.logging.log4j.util.PerformanceSensitive;
public final class StringMatchFilter extends AbstractFilter {
public static final String ATTR_MATCH = "match";
+
private final String text;
- private StringMatchFilter(final String text, final Result onMatch, final
Result onMismatch) {
- super(onMatch, onMismatch);
- this.text = text;
+ private StringMatchFilter(final Builder builder) {
+ super(builder.getOnMatch(), builder.getOnMismatch());
+ this.text = Assert.requireNonEmpty(builder.text, "The 'text' argument
must not be null or empty.");
+ }
+
+ /**
+ * Returns the text this filter searches for in event messages.
+ *
+ * @return the text this filter searches for in event messages
+ * @since 3.0.0
+ */
+ public String getText() {
+ return text;
}
@Override
@@ -230,28 +245,44 @@ public final class StringMatchFilter extends
AbstractFilter {
}
@PluginFactory
- public static StringMatchFilter.Builder newBuilder() {
- return new StringMatchFilter.Builder();
+ public static Builder newBuilder() {
+ return new Builder();
}
- public static class Builder extends
AbstractFilterBuilder<StringMatchFilter.Builder>
- implements
org.apache.logging.log4j.core.util.Builder<StringMatchFilter> {
+ public static class Builder extends AbstractFilterBuilder<Builder>
+ implements
org.apache.logging.log4j.plugins.util.Builder<StringMatchFilter> {
+
@PluginBuilderAttribute
- private String text = "";
+ @Required(message = "No text provided for StringMatchFilter")
+ private String text;
/**
* Sets the text to search in event messages.
* @param text the text to search in event messages.
* @return this instance.
+ * @since 3.0.0
*/
- public StringMatchFilter.Builder setMatchString(final String text) {
- this.text = text;
+ public Builder setText(@NonNull final String text) {
+ Objects.requireNonNull(text, "The 'text' argument must not be
null.");
+ this.text = Assert.requireNonEmpty(text, "The 'text' argument must
not be empty.");
return this;
}
+ /**
+ * @deprecated since 3.0.0, use {@link #setText(String)} instead.
+ */
+ @Deprecated(since = "3.0.0")
+ public Builder setMatchString(final String text) {
+ return setText(text);
+ }
+
@Override
public StringMatchFilter build() {
- return new StringMatchFilter(this.text, this.getOnMatch(),
this.getOnMismatch());
+ if (this.text == null) {
+ LOGGER.error("Unable to create StringMatchFilter: The 'text'
attribute must be configured.");
+ return null;
+ }
+ return new StringMatchFilter(this);
}
}
}