vy commented on code in PR #3512:
URL: https://github.com/apache/logging-log4j2/pull/3512#discussion_r1995087013
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -100,59 +242,191 @@ private String targetMessageTest(final Message message) {
: message.getFormattedMessage();
}
- private Result filter(final String msg) {
- if (msg == null) {
- return onMismatch;
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "useRawMessage=" + useRawMessage + ", pattern=" +
pattern.toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @return the new builder instance
+ */
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * A {@link RegexFilter} builder instance.
+ */
+ public static final class Builder extends
AbstractFilterBuilder<RegexFilter.Builder>
+ implements org.apache.logging.log4j.core.util.Builder<RegexFilter>
{
+
+ /* NOTE: LOG4J-3086 - No patternFlags in builder - this functionality
has been deprecated/removed. */
+
+ /**
+ * The regular expression to match.
+ */
+ @PluginBuilderAttribute
+ @Required(message = "No 'regex' provided for RegexFilter")
+ private @Nullable String regex;
+
+ /**
+ * If {@code true}, for {@link ParameterizedMessage}, {@link
StringFormattedMessage},
+ * and {@link MessageFormatMessage}, the message format pattern; for
{@link StructuredDataMessage},
+ * the message field will be used as the match target.
+ */
+ @PluginBuilderAttribute
+ private @Nullable Boolean useRawMsg;
+
+ /** Private constructor. */
+ private Builder() {
+ super();
+ }
+
+ /**
+ * Sets the regular-expression.
+ *
+ * @param regex the regular-expression
+ * @return this builder
+ */
+ public Builder setRegex(final String regex) {
+ this.regex = Assert.requireNonEmpty(regex, "The 'regex' attribute
must not be null or empty.");
+ return this;
+ }
+
+ /**
+ * Sets the use raw msg flag.
+ *
+ * @param useRawMsg {@code true} if the message format-patter/field
will be used as match target;
+ * otherwise, {@code false}
+ * @return this builder
+ */
+ public Builder setUseRawMsg(final boolean useRawMsg) {
+ this.useRawMsg = useRawMsg;
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isValid() {
+ return (Strings.isNotEmpty(this.regex));
Review Comment:
```suggestion
return Strings.isNotEmpty(this.regex);
```
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -29,68 +29,210 @@
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import
org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.core.util.Assert;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.MessageFormatMessage;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.message.StringFormattedMessage;
import org.apache.logging.log4j.message.StructuredDataMessage;
+import org.apache.logging.log4j.util.Strings;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
/**
- * A filter that matches the given regular expression pattern against messages.
+ * This filter returns the {@code onMatch} result if the message exactly
matches the configured
+ * "{@code regex}" regular-expression pattern; otherwise, it returns the
{@code onMismatch} result.
*/
@Plugin(name = "RegexFilter", category = Node.CATEGORY, elementType =
Filter.ELEMENT_TYPE, printObject = true)
+@NullMarked
public final class RegexFilter extends AbstractFilter {
- private static final int DEFAULT_PATTERN_FLAGS = 0;
+ /** The pattern compiled from the regular-expression. */
private final Pattern pattern;
+
+ /** Flag: if {@code true} use message format-pattern / field for the match
target. */
private final boolean useRawMessage;
- private RegexFilter(final boolean raw, final Pattern pattern, final Result
onMatch, final Result onMismatch) {
- super(onMatch, onMismatch);
- this.pattern = pattern;
- this.useRawMessage = raw;
+ /**
+ * Constructs a new {@code RegexFilter} configured by the given builder.
+ * @param builder the builder
+ * @throws IllegalArgumentException if the regular expression is not
configured or cannot be compiled to a pattern
+ */
+ private RegexFilter(final Builder builder) {
+
+ super(builder);
+
+ if (Strings.isBlank(builder.regex)) {
+ throw new IllegalArgumentException("The 'regex' attribute must not
be null or empty.");
+ }
+
+ this.useRawMessage = Boolean.TRUE.equals(builder.useRawMsg);
+
+ try {
+ this.pattern = Pattern.compile(builder.regex);
+ } catch (final Exception ex) {
+ throw new IllegalArgumentException("Unable to compile regular
expression: '" + builder.regex + "'.", ex);
+ }
+ }
+
+ /**
+ * Returns the compiled regular-expression pattern.
+ * @return the pattern (will never be {@code null}
+ */
+ public Pattern getPattern() {
+ return this.pattern;
+ }
+
+ /**
+ * Returns the regular-expression.
+ * @return the regular-expression (it may be an empty string but never
{@code null})
+ */
+ public String getRegex() {
+ return this.pattern.pattern();
+ }
+
+ /**
+ * Returns whether the raw-message should be used.
+ * @return {@code true} if the raw message should be used; otherwise,
{@code false}
+ */
+ public boolean isUseRawMessage() {
+ return this.useRawMessage;
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation performs the filter evaluation against the given
message formatted with
+ * the given parameters.
+ * </p>
+ * <p>
+ * The following method arguments are ignored by this filter method
implementation:
+ * <ul>
+ * <li>{@code logger}</li>
+ * <li>{@code level}</li>
+ * <li>{@code marker}</li>
+ * </ul>
+ * </p>
+ */
@Override
public Result filter(
- final Logger logger, final Level level, final Marker marker, final
String msg, final Object... params) {
- if (useRawMessage || params == null || params.length == 0) {
- return filter(msg);
- }
- return filter(ParameterizedMessage.format(msg, params));
+ final @Nullable Logger logger,
+ final @Nullable Level level,
+ final @Nullable Marker marker,
+ final @Nullable String msg,
+ final @Nullable Object @Nullable ... params) {
+
+ return (useRawMessage || params == null || params.length == 0)
+ ? filter(msg)
+ : filter(ParameterizedMessage.format(msg, params));
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation performs the filter evaluation against the given
message.
+ * </p>
+ * <p>
+ * The following method arguments are ignored by this filter method
implementation:
+ * <ul>
+ * <li>{@code logger}</li>
+ * <li>{@code level}</li>
+ * <li>{@code marker}</li>
+ * <li>{@code throwable}</li>
+ * </ul>
+ * </p>
+ */
@Override
public Result filter(
- final Logger logger, final Level level, final Marker marker, final
Object msg, final Throwable t) {
- if (msg == null) {
- return onMismatch;
- }
- return filter(msg.toString());
+ final @Nullable Logger logger,
+ final @Nullable Level level,
+ final @Nullable Marker marker,
+ final @Nullable Object message,
+ final @Nullable Throwable throwable) {
+
+ return (message == null) ? this.onMismatch :
filter(message.toString());
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation performs the filter evaluation against the given
message.
+ * </p>
+ * <p>
+ * The following method arguments are ignored by this filter method
implementation:
+ * <ul>
+ * <li>{@code logger}</li>
+ * <li>{@code level}</li>
+ * <li>{@code marker}</li>
+ * <li>{@code throwable}</li>
+ * </ul>
+ * </p>
+ */
@Override
public Result filter(
- final Logger logger, final Level level, final Marker marker, final
Message msg, final Throwable t) {
- if (msg == null) {
- return onMismatch;
- }
- final String text = targetMessageTest(msg);
- return filter(text);
+ final @Nullable Logger logger,
+ final @Nullable Level level,
+ final @Nullable Marker marker,
+ final @Nullable Message message,
+ final @Nullable Throwable throwable) {
+ return (message == null) ? this.onMismatch :
filter(getMessageTextByType(message));
}
+ /**
+ * {@inheritDoc}
+ *
+ * @throws NullPointerException if the {@code event} argument is {@code
null}
+ */
@Override
public Result filter(final LogEvent event) {
- final String text = targetMessageTest(event.getMessage());
- return filter(text);
+ Objects.requireNonNull(event, "The 'event' argument must not be
null.");
Review Comment:
```suggestion
Objects.requireNonNull(event, "event");
```
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -100,59 +242,191 @@ private String targetMessageTest(final Message message) {
: message.getFormattedMessage();
}
- private Result filter(final String msg) {
- if (msg == null) {
- return onMismatch;
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "useRawMessage=" + useRawMessage + ", pattern=" +
pattern.toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @return the new builder instance
+ */
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * A {@link RegexFilter} builder instance.
+ */
+ public static final class Builder extends
AbstractFilterBuilder<RegexFilter.Builder>
+ implements org.apache.logging.log4j.core.util.Builder<RegexFilter>
{
+
+ /* NOTE: LOG4J-3086 - No patternFlags in builder - this functionality
has been deprecated/removed. */
+
+ /**
+ * The regular expression to match.
+ */
+ @PluginBuilderAttribute
+ @Required(message = "No 'regex' provided for RegexFilter")
Review Comment:
Please don't provide a failure message for cases where _the failure system_
should be providing the necessary context.
```suggestion
@Required
```
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -100,59 +242,191 @@ private String targetMessageTest(final Message message) {
: message.getFormattedMessage();
}
- private Result filter(final String msg) {
- if (msg == null) {
- return onMismatch;
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "useRawMessage=" + useRawMessage + ", pattern=" +
pattern.toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @return the new builder instance
+ */
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * A {@link RegexFilter} builder instance.
+ */
+ public static final class Builder extends
AbstractFilterBuilder<RegexFilter.Builder>
+ implements org.apache.logging.log4j.core.util.Builder<RegexFilter>
{
+
+ /* NOTE: LOG4J-3086 - No patternFlags in builder - this functionality
has been deprecated/removed. */
+
+ /**
+ * The regular expression to match.
+ */
+ @PluginBuilderAttribute
+ @Required(message = "No 'regex' provided for RegexFilter")
+ private @Nullable String regex;
+
+ /**
+ * If {@code true}, for {@link ParameterizedMessage}, {@link
StringFormattedMessage},
+ * and {@link MessageFormatMessage}, the message format pattern; for
{@link StructuredDataMessage},
+ * the message field will be used as the match target.
+ */
+ @PluginBuilderAttribute
+ private @Nullable Boolean useRawMsg;
+
+ /** Private constructor. */
+ private Builder() {
+ super();
+ }
+
+ /**
+ * Sets the regular-expression.
+ *
+ * @param regex the regular-expression
+ * @return this builder
+ */
+ public Builder setRegex(final String regex) {
+ this.regex = Assert.requireNonEmpty(regex, "The 'regex' attribute
must not be null or empty.");
+ return this;
+ }
+
+ /**
+ * Sets the use raw msg flag.
+ *
+ * @param useRawMsg {@code true} if the message format-patter/field
will be used as match target;
+ * otherwise, {@code false}
+ * @return this builder
+ */
+ public Builder setUseRawMsg(final boolean useRawMsg) {
+ this.useRawMsg = useRawMsg;
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isValid() {
+ return (Strings.isNotEmpty(this.regex));
+ }
+
+ /**
+ * Builds and returns a {@link RegexFilter} instance configured by
this builder.
+ *
+ * @return the created {@link RegexFilter} or {@code null} if the
builder is misconfigured
+ */
+ @Override
+ public @Nullable RegexFilter build() {
+
+ // validate the "regex" attribute
+ if (Strings.isEmpty(this.regex)) {
+ LOGGER.error("Unable to create RegexFilter: The 'regex'
attribute be set to a non-empty String.");
+ return null;
+ }
+
+ // build with *safety* to not throw exceptions
+ try {
+ return new RegexFilter(this);
+ } catch (final Exception ex) {
+ LOGGER.error("Unable to create RegexFilter. {}",
ex.getMessage(), ex);
+ return null;
+ }
}
- final Matcher m = pattern.matcher(msg);
- return m.matches() ? onMatch : onMismatch;
}
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("useRaw=").append(useRawMessage);
- sb.append(", pattern=").append(pattern.toString());
- return sb.toString();
+ /*
+ * DEPRECATIONS:
+ * The constructor/fields/methods below have been deprecated.
+ * - the 'create***' factory methods should no longer be used - use the
builder instead
+ * - pattern-flags should now be passed via the regular expression itself
+ */
+
+ /**
+ * @deprecated pattern flags have been deprecated - they can just be
included in the regex-expression.
+ */
+ @Deprecated
+ private static final int DEFAULT_PATTERN_FLAGS = 0;
Review Comment:
AFAIU, this constant is only used in `toPatternFlags()`, could you move it
into that method, please?
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -100,59 +242,191 @@ private String targetMessageTest(final Message message) {
: message.getFormattedMessage();
}
- private Result filter(final String msg) {
- if (msg == null) {
- return onMismatch;
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "useRawMessage=" + useRawMessage + ", pattern=" +
pattern.toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @return the new builder instance
+ */
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * A {@link RegexFilter} builder instance.
+ */
+ public static final class Builder extends
AbstractFilterBuilder<RegexFilter.Builder>
+ implements org.apache.logging.log4j.core.util.Builder<RegexFilter>
{
+
+ /* NOTE: LOG4J-3086 - No patternFlags in builder - this functionality
has been deprecated/removed. */
+
+ /**
+ * The regular expression to match.
+ */
+ @PluginBuilderAttribute
+ @Required(message = "No 'regex' provided for RegexFilter")
+ private @Nullable String regex;
+
+ /**
+ * If {@code true}, for {@link ParameterizedMessage}, {@link
StringFormattedMessage},
+ * and {@link MessageFormatMessage}, the message format pattern; for
{@link StructuredDataMessage},
+ * the message field will be used as the match target.
+ */
+ @PluginBuilderAttribute
+ private @Nullable Boolean useRawMsg;
+
+ /** Private constructor. */
+ private Builder() {
+ super();
+ }
+
+ /**
+ * Sets the regular-expression.
+ *
+ * @param regex the regular-expression
+ * @return this builder
+ */
+ public Builder setRegex(final String regex) {
+ this.regex = Assert.requireNonEmpty(regex, "The 'regex' attribute
must not be null or empty.");
+ return this;
+ }
+
+ /**
+ * Sets the use raw msg flag.
+ *
+ * @param useRawMsg {@code true} if the message format-patter/field
will be used as match target;
+ * otherwise, {@code false}
+ * @return this builder
+ */
+ public Builder setUseRawMsg(final boolean useRawMsg) {
+ this.useRawMsg = useRawMsg;
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isValid() {
+ return (Strings.isNotEmpty(this.regex));
+ }
+
+ /**
+ * Builds and returns a {@link RegexFilter} instance configured by
this builder.
+ *
+ * @return the created {@link RegexFilter} or {@code null} if the
builder is misconfigured
+ */
+ @Override
+ public @Nullable RegexFilter build() {
+
+ // validate the "regex" attribute
+ if (Strings.isEmpty(this.regex)) {
+ LOGGER.error("Unable to create RegexFilter: The 'regex'
attribute be set to a non-empty String.");
+ return null;
+ }
+
+ // build with *safety* to not throw exceptions
+ try {
+ return new RegexFilter(this);
+ } catch (final Exception ex) {
+ LOGGER.error("Unable to create RegexFilter. {}",
ex.getMessage(), ex);
+ return null;
+ }
}
Review Comment:
We had [a `dev@` discussion about
this](https://lists.apache.org/thread/h2oydyk6xld47ljttqvflbt4530o73vw), and
the conclusion is to throw exception on failures while building components.
Would you mind updating this `build()` logic accordingly, please?
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -100,59 +242,191 @@ private String targetMessageTest(final Message message) {
: message.getFormattedMessage();
}
- private Result filter(final String msg) {
- if (msg == null) {
- return onMismatch;
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "useRawMessage=" + useRawMessage + ", pattern=" +
pattern.toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @return the new builder instance
+ */
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * A {@link RegexFilter} builder instance.
+ */
+ public static final class Builder extends
AbstractFilterBuilder<RegexFilter.Builder>
+ implements org.apache.logging.log4j.core.util.Builder<RegexFilter>
{
+
+ /* NOTE: LOG4J-3086 - No patternFlags in builder - this functionality
has been deprecated/removed. */
+
+ /**
+ * The regular expression to match.
+ */
+ @PluginBuilderAttribute
+ @Required(message = "No 'regex' provided for RegexFilter")
+ private @Nullable String regex;
+
+ /**
+ * If {@code true}, for {@link ParameterizedMessage}, {@link
StringFormattedMessage},
+ * and {@link MessageFormatMessage}, the message format pattern; for
{@link StructuredDataMessage},
+ * the message field will be used as the match target.
+ */
+ @PluginBuilderAttribute
+ private @Nullable Boolean useRawMsg;
+
+ /** Private constructor. */
+ private Builder() {
+ super();
+ }
+
+ /**
+ * Sets the regular-expression.
+ *
+ * @param regex the regular-expression
+ * @return this builder
+ */
+ public Builder setRegex(final String regex) {
+ this.regex = Assert.requireNonEmpty(regex, "The 'regex' attribute
must not be null or empty.");
+ return this;
+ }
+
+ /**
+ * Sets the use raw msg flag.
+ *
+ * @param useRawMsg {@code true} if the message format-patter/field
will be used as match target;
+ * otherwise, {@code false}
+ * @return this builder
+ */
+ public Builder setUseRawMsg(final boolean useRawMsg) {
+ this.useRawMsg = useRawMsg;
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isValid() {
+ return (Strings.isNotEmpty(this.regex));
+ }
+
+ /**
+ * Builds and returns a {@link RegexFilter} instance configured by
this builder.
+ *
+ * @return the created {@link RegexFilter} or {@code null} if the
builder is misconfigured
+ */
+ @Override
+ public @Nullable RegexFilter build() {
+
+ // validate the "regex" attribute
+ if (Strings.isEmpty(this.regex)) {
+ LOGGER.error("Unable to create RegexFilter: The 'regex'
attribute be set to a non-empty String.");
+ return null;
+ }
+
+ // build with *safety* to not throw exceptions
+ try {
+ return new RegexFilter(this);
+ } catch (final Exception ex) {
+ LOGGER.error("Unable to create RegexFilter. {}",
ex.getMessage(), ex);
+ return null;
+ }
}
- final Matcher m = pattern.matcher(msg);
- return m.matches() ? onMatch : onMismatch;
}
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("useRaw=").append(useRawMessage);
- sb.append(", pattern=").append(pattern.toString());
- return sb.toString();
+ /*
+ * DEPRECATIONS:
+ * The constructor/fields/methods below have been deprecated.
+ * - the 'create***' factory methods should no longer be used - use the
builder instead
+ * - pattern-flags should now be passed via the regular expression itself
+ */
+
+ /**
+ * @deprecated pattern flags have been deprecated - they can just be
included in the regex-expression.
+ */
+ @Deprecated
+ private static final int DEFAULT_PATTERN_FLAGS = 0;
+
+ /**
+ * @deprecated - pattern flags no longer supported.
+ */
+ @Deprecated
+ private String[] patternFlags = new String[0];
+
+ /**
+ * @deprecated use {@link RegexFilter.Builder} instead
+ */
+ @Deprecated
+ @SuppressWarnings("MagicConstant")
+ private RegexFilter(
+ final String regex,
+ final boolean useRawMessage,
+ final @Nullable String @Nullable [] patternFlags,
+ final @Nullable Result onMatch,
+ final @Nullable Result onMismatch) {
+ super(onMatch, onMismatch);
+ Objects.requireNonNull(regex, "The 'regex' argument must be provided
for RegexFilter");
+ this.patternFlags = patternFlags == null ? new String[0] :
patternFlags.clone();
+ try {
+ int flags = toPatternFlags(this.patternFlags);
+ this.pattern = Pattern.compile(regex, flags);
+ } catch (final Exception ex) {
+ throw new IllegalArgumentException("Unable to compile regular
expression: '" + regex + "'.", ex);
+ }
+ this.useRawMessage = useRawMessage;
+ }
+
+ /**
+ * Returns the pattern-flags applied to the regular-expression when
compiling the pattern.
+ *
+ * @return the pattern-flags (maybe empty but never {@code null}
+ * @deprecated pattern-flags are no longer supported
+ */
+ @Deprecated
+ public String[] getPatternFlags() {
+ return this.patternFlags.clone();
}
Review Comment:
We're adding a new deprecated method? Why don't we simply not add it?
##########
log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java:
##########
@@ -100,59 +242,191 @@ private String targetMessageTest(final Message message) {
: message.getFormattedMessage();
}
- private Result filter(final String msg) {
- if (msg == null) {
- return onMismatch;
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "useRawMessage=" + useRawMessage + ", pattern=" +
pattern.toString();
+ }
+
+ /**
+ * Creates a new builder instance.
+ * @return the new builder instance
+ */
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * A {@link RegexFilter} builder instance.
+ */
+ public static final class Builder extends
AbstractFilterBuilder<RegexFilter.Builder>
+ implements org.apache.logging.log4j.core.util.Builder<RegexFilter>
{
+
+ /* NOTE: LOG4J-3086 - No patternFlags in builder - this functionality
has been deprecated/removed. */
+
+ /**
+ * The regular expression to match.
+ */
+ @PluginBuilderAttribute
+ @Required(message = "No 'regex' provided for RegexFilter")
+ private @Nullable String regex;
+
+ /**
+ * If {@code true}, for {@link ParameterizedMessage}, {@link
StringFormattedMessage},
+ * and {@link MessageFormatMessage}, the message format pattern; for
{@link StructuredDataMessage},
+ * the message field will be used as the match target.
+ */
+ @PluginBuilderAttribute
+ private @Nullable Boolean useRawMsg;
+
+ /** Private constructor. */
+ private Builder() {
+ super();
+ }
+
+ /**
+ * Sets the regular-expression.
+ *
+ * @param regex the regular-expression
+ * @return this builder
+ */
+ public Builder setRegex(final String regex) {
+ this.regex = Assert.requireNonEmpty(regex, "The 'regex' attribute
must not be null or empty.");
+ return this;
+ }
+
+ /**
+ * Sets the use raw msg flag.
+ *
+ * @param useRawMsg {@code true} if the message format-patter/field
will be used as match target;
+ * otherwise, {@code false}
+ * @return this builder
+ */
+ public Builder setUseRawMsg(final boolean useRawMsg) {
+ this.useRawMsg = useRawMsg;
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isValid() {
+ return (Strings.isNotEmpty(this.regex));
+ }
+
+ /**
+ * Builds and returns a {@link RegexFilter} instance configured by
this builder.
+ *
+ * @return the created {@link RegexFilter} or {@code null} if the
builder is misconfigured
+ */
+ @Override
+ public @Nullable RegexFilter build() {
+
+ // validate the "regex" attribute
+ if (Strings.isEmpty(this.regex)) {
+ LOGGER.error("Unable to create RegexFilter: The 'regex'
attribute be set to a non-empty String.");
+ return null;
+ }
+
+ // build with *safety* to not throw exceptions
+ try {
+ return new RegexFilter(this);
+ } catch (final Exception ex) {
+ LOGGER.error("Unable to create RegexFilter. {}",
ex.getMessage(), ex);
+ return null;
+ }
}
- final Matcher m = pattern.matcher(msg);
- return m.matches() ? onMatch : onMismatch;
}
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("useRaw=").append(useRawMessage);
- sb.append(", pattern=").append(pattern.toString());
- return sb.toString();
+ /*
+ * DEPRECATIONS:
+ * The constructor/fields/methods below have been deprecated.
+ * - the 'create***' factory methods should no longer be used - use the
builder instead
+ * - pattern-flags should now be passed via the regular expression itself
+ */
+
+ /**
+ * @deprecated pattern flags have been deprecated - they can just be
included in the regex-expression.
+ */
+ @Deprecated
+ private static final int DEFAULT_PATTERN_FLAGS = 0;
+
+ /**
+ * @deprecated - pattern flags no longer supported.
+ */
+ @Deprecated
+ private String[] patternFlags = new String[0];
+
+ /**
+ * @deprecated use {@link RegexFilter.Builder} instead
+ */
+ @Deprecated
+ @SuppressWarnings("MagicConstant")
+ private RegexFilter(
+ final String regex,
+ final boolean useRawMessage,
+ final @Nullable String @Nullable [] patternFlags,
+ final @Nullable Result onMatch,
+ final @Nullable Result onMismatch) {
+ super(onMatch, onMismatch);
+ Objects.requireNonNull(regex, "The 'regex' argument must be provided
for RegexFilter");
+ this.patternFlags = patternFlags == null ? new String[0] :
patternFlags.clone();
+ try {
+ int flags = toPatternFlags(this.patternFlags);
+ this.pattern = Pattern.compile(regex, flags);
+ } catch (final Exception ex) {
+ throw new IllegalArgumentException("Unable to compile regular
expression: '" + regex + "'.", ex);
+ }
+ this.useRawMessage = useRawMessage;
+ }
+
+ /**
+ * Returns the pattern-flags applied to the regular-expression when
compiling the pattern.
+ *
+ * @return the pattern-flags (maybe empty but never {@code null}
+ * @deprecated pattern-flags are no longer supported
+ */
+ @Deprecated
+ public String[] getPatternFlags() {
+ return this.patternFlags.clone();
}
/**
* Creates a Filter that matches a regular expression.
*
- * @param regex
- * The regular expression to match.
- * @param patternFlags
- * An array of Strings where each String is a {@link
Pattern#compile(String, int)} compilation flag.
- * @param useRawMsg
- * If {@code true}, for {@link ParameterizedMessage}, {@link
StringFormattedMessage}, and {@link MessageFormatMessage}, the message format
pattern; for {@link StructuredDataMessage}, the message field will be used as
the match target.
- * @param match
- * The action to perform when a match occurs.
- * @param mismatch
- * The action to perform when a mismatch occurs.
+ * @param regex The regular expression to match.
+ * @param patternFlags An array of Strings where each String is a {@link
Pattern#compile(String, int)} compilation flag.
+ * (no longer used - pattern flags can be embedded in
regex-expression.
+ * @param useRawMsg If {@code true}, for {@link ParameterizedMessage},
{@link StringFormattedMessage},
+ * and {@link MessageFormatMessage}, the message
format pattern; for {@link StructuredDataMessage},
+ * the message field will be used as the match target.
+ * @param match The action to perform when a match occurs.
+ * @param mismatch The action to perform when a mismatch occurs.
* @return The RegexFilter.
- * @throws IllegalAccessException When there is no access to the
definition of the specified member.
+ * @throws IllegalAccessException When there is no access to the
definition of the specified member.
* @throws IllegalArgumentException When passed an illegal or
inappropriate argument.
+ * @deprecated use {@link #newBuilder} to instantiate builder
*/
- // TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
- @PluginFactory
+ @Deprecated
public static RegexFilter createFilter(
// @formatter:off
@PluginAttribute("regex") final String regex,
- @PluginElement("PatternFlags") final String[] patternFlags,
- @PluginAttribute("useRawMsg") final Boolean useRawMsg,
- @PluginAttribute("onMatch") final Result match,
- @PluginAttribute("onMismatch") final Result mismatch)
+ @PluginElement("PatternFlags") final String @Nullable []
patternFlags,
+ @PluginAttribute("useRawMsg") final @Nullable Boolean useRawMsg,
+ @PluginAttribute("onMatch") final @Nullable Result match,
+ @PluginAttribute("onMismatch") final @Nullable Result mismatch)
// @formatter:on
throws IllegalArgumentException, IllegalAccessException {
- if (regex == null) {
- LOGGER.error("A regular expression must be provided for
RegexFilter");
- return null;
- }
- return new RegexFilter(
- Boolean.TRUE.equals(useRawMsg), Pattern.compile(regex,
toPatternFlags(patternFlags)), match, mismatch);
+
+ // LOG4J-3086 - pattern-flags can be embedded in RegEx expression
+ Objects.requireNonNull(regex, "The 'regex' argument must not be
null.");
Review Comment:
```suggestion
Objects.requireNonNull(regex, "regex");
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]