Skip to content

Commit 3827a0c

Browse files
committed
A few more improvements + added tests (apache#3086)
1 parent cdd9eed commit 3827a0c

File tree

2 files changed

+142
-26
lines changed

2 files changed

+142
-26
lines changed

log4j-core-test/src/test/java/org/apache/logging/log4j/core/filter/RegexFilterTest.java

+111-15
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
import static org.hamcrest.CoreMatchers.equalTo;
2020
import static org.hamcrest.MatcherAssert.assertThat;
2121
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
22+
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
import static org.junit.jupiter.api.Assertions.assertFalse;
2224
import static org.junit.jupiter.api.Assertions.assertNotNull;
2325
import static org.junit.jupiter.api.Assertions.assertNull;
2426
import static org.junit.jupiter.api.Assertions.assertSame;
27+
import static org.junit.jupiter.api.Assertions.assertThrows;
2528
import static org.junit.jupiter.api.Assertions.assertTrue;
2629

2730
import org.apache.logging.log4j.Level;
@@ -89,38 +92,131 @@ public void testDotAllPattern() throws Exception {
8992
}
9093

9194
@Test
92-
public void testNoMsg() throws Exception {
93-
final RegexFilter filter = RegexFilter.createFilter(".* test .*", null, false, null, null);
95+
void testNoMsg() {
96+
97+
final RegexFilter filter =
98+
RegexFilter.newBuilder()
99+
.setRegex(".* test .*")
100+
.setUseRawMsg(false)
101+
.build();
102+
103+
assertNotNull(filter);
104+
94105
filter.start();
106+
95107
assertTrue(filter.isStarted());
96108
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
97109
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Message) null, (Throwable) null));
98110
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, null, (Object[]) null));
99111
}
100112

101113
@Test
102-
public void testParameterizedMsg() throws Exception {
114+
void testParameterizedMsg() {
103115
final String msg = "params {} {}";
104116
final Object[] params = {"foo", "bar"};
105117

106118
// match against raw message
107-
final RegexFilter rawFilter = RegexFilter.createFilter(
108-
"params \\{\\} \\{\\}",
109-
null,
110-
true, // useRawMsg
111-
Result.ACCEPT,
112-
Result.DENY);
119+
final RegexFilter rawFilter =
120+
RegexFilter.newBuilder()
121+
.setRegex("params \\{\\} \\{\\}")
122+
.setUseRawMsg(true)
123+
.setOnMatch(Result.ACCEPT)
124+
.setOnMismatch(Result.DENY)
125+
.build();
126+
127+
assertNotNull(rawFilter);
128+
113129
final Result rawResult = rawFilter.filter(null, null, null, msg, params);
114130
assertThat(rawResult, equalTo(Result.ACCEPT));
115131

116132
// match against formatted message
117-
final RegexFilter fmtFilter = RegexFilter.createFilter(
118-
"params foo bar",
119-
null,
120-
false, // useRawMsg
121-
Result.ACCEPT,
122-
Result.DENY);
133+
final RegexFilter fmtFilter =
134+
RegexFilter.newBuilder()
135+
.setRegex("params foo bar")
136+
.setUseRawMsg(false)
137+
.setOnMatch(Result.ACCEPT)
138+
.setOnMismatch(Result.DENY).build();
139+
140+
assertNotNull(fmtFilter);
141+
123142
final Result fmtResult = fmtFilter.filter(null, null, null, msg, params);
124143
assertThat(fmtResult, equalTo(Result.ACCEPT));
125144
}
145+
146+
/**
147+
* A builder with no 'regex' expression should both be invalid and return null on 'build()'.
148+
*/
149+
@Test
150+
void testWithValidRegex() {
151+
152+
final String regex = "^[a-zA-Z0-9_]+$"; // matches alphanumeric with underscores
153+
154+
final RegexFilter.Builder builder =
155+
RegexFilter.newBuilder().setRegex(regex).setUseRawMsg(false).setOnMatch(Result.ACCEPT).setOnMismatch(Result.DENY);
156+
157+
assertTrue(builder.isValid());
158+
159+
final RegexFilter filter = builder.build();
160+
161+
assertNotNull(filter);
162+
163+
assertEquals(Result.ACCEPT, filter.filter("Hello_123"));
164+
165+
assertEquals(Result.DENY, filter.filter("Hello@123"));
166+
167+
assertEquals(regex, filter.getRegex());
168+
}
169+
170+
@Test
171+
void testRegexFilterGetters() {
172+
173+
final String regex = "^[a-zA-Z0-9_]+$"; // matches alphanumeric with underscores
174+
175+
final RegexFilter filter =
176+
RegexFilter.newBuilder()
177+
.setRegex(regex)
178+
.setUseRawMsg(false)
179+
.setOnMatch(Result.ACCEPT)
180+
.setOnMismatch(Result.DENY)
181+
.build();
182+
183+
assertNotNull(filter);
184+
185+
assertEquals(regex, filter.getRegex());
186+
assertFalse(filter.isUseRawMessage());
187+
assertEquals(Result.ACCEPT, filter.getOnMatch());
188+
assertEquals(Result.DENY, filter.getOnMismatch());
189+
assertNotNull(filter.getPattern());
190+
assertEquals(regex, filter.getPattern().pattern());
191+
}
192+
193+
/**
194+
* A builder with no 'regex' expression should both be invalid and return null on 'build()'.
195+
*/
196+
@Test
197+
void testBuilderWithoutRegexNotValid() {
198+
199+
final RegexFilter.Builder builder = RegexFilter.newBuilder();
200+
201+
assertFalse(builder.isValid());
202+
203+
assertNull(builder.build());
204+
205+
}
206+
207+
/**
208+
* A builder with an invalid 'regex' expression should return null on 'build()'.
209+
*/
210+
@Test
211+
void testBuilderWithInvalidRegexNotValid() {
212+
213+
final RegexFilter.Builder builder = RegexFilter.newBuilder();
214+
215+
builder.setRegex("[a-z");
216+
217+
assertFalse(builder.isValid());
218+
219+
assertNull(builder.build());
220+
221+
}
126222
}

log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java

+31-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Comparator;
2222
import java.util.Objects;
2323
import java.util.regex.Pattern;
24+
import java.util.regex.PatternSyntaxException;
2425
import org.apache.logging.log4j.Level;
2526
import org.apache.logging.log4j.Marker;
2627
import org.apache.logging.log4j.core.Filter;
@@ -51,9 +52,6 @@
5152
@Plugin
5253
public final class RegexFilter extends AbstractFilter {
5354

54-
/** The regular-expression. */
55-
private final String regex;
56-
5755
/** The pattern compiled from the regular-expression. */
5856
private final Pattern pattern;
5957

@@ -69,13 +67,12 @@ private RegexFilter(final Builder builder) {
6967

7068
super(builder);
7169

72-
this.regex = builder.regex;
7370
this.useRawMessage = Boolean.TRUE.equals(builder.useRawMsg);
7471

7572
try {
76-
this.pattern = Pattern.compile(regex);
73+
this.pattern = Pattern.compile(builder.regex);
7774
} catch (final Exception ex) {
78-
throw new IllegalArgumentException("Unable to compile regular expression: '" + regex + "'.", ex);
75+
throw new IllegalArgumentException("Unable to compile regular expression: '" + builder.regex + "'.", ex);
7976
}
8077
}
8178

@@ -84,7 +81,7 @@ private RegexFilter(final Builder builder) {
8481
* @return the regular-expression (it may be an empty string but never {@code null})
8582
*/
8683
public String getRegex() {
87-
return this.regex;
84+
return this.pattern.pattern();
8885
}
8986

9087
/**
@@ -143,7 +140,7 @@ public Result filter(final LogEvent event) {
143140
* @param msg the message
144141
* @return the filter result
145142
*/
146-
private Result filter(final String msg) {
143+
public Result filter(final String msg) {
147144
if (msg == null) {
148145
return onMismatch;
149146
}
@@ -188,7 +185,7 @@ private String getMessageTextByType(final Message message) {
188185

189186
@Override
190187
public String toString() {
191-
return "useRawMessage=" + useRawMessage + ", regex=" + regex + ", pattern=" + pattern.toString();
188+
return "useRawMessage=" + useRawMessage + ", pattern=" + pattern.toString();
192189
}
193190

194191
/**
@@ -258,7 +255,11 @@ public Builder setUseRawMsg(final boolean useRawMsg) {
258255
*/
259256
@Override
260257
public boolean isValid() {
261-
return (regex != null);
258+
boolean valid = true;
259+
if (!isRegexValid()) {
260+
valid = false;
261+
}
262+
return valid;
262263
}
263264

264265
/**
@@ -280,6 +281,25 @@ public RegexFilter build() {
280281
return null;
281282
}
282283
}
284+
285+
/**
286+
* Validates the 'regex' attribute.
287+
* <p>
288+
* If the regular-expression is not set, or cannot be compiled to a valid pattern the validation will fail.
289+
* </p>
290+
* @return {@code true} if the regular-expression is valid; otherwise, {@code false}
291+
*/
292+
private boolean isRegexValid() {
293+
if (regex == null) {
294+
return false;
295+
}
296+
try {
297+
Pattern.compile(regex);
298+
} catch (final PatternSyntaxException ex) {
299+
return false;
300+
}
301+
return true;
302+
}
283303
}
284304

285305
/*
@@ -313,7 +333,7 @@ private RegexFilter(
313333
final Result onMatch,
314334
final Result onMismatch) {
315335
super(onMatch, onMismatch);
316-
this.regex = Objects.requireNonNull(regex, "The 'regex' argument must be provided for RegexFilter");
336+
Objects.requireNonNull(regex, "The 'regex' argument must be provided for RegexFilter");
317337
this.patternFlags = patternFlags == null ? new String[0] : patternFlags.clone();
318338
try {
319339
int flags = toPatternFlags(this.patternFlags);

0 commit comments

Comments
 (0)