Skip to content

Commit 7ef0c54

Browse files
jethomas-tsiJWT007
authored andcommitted
A few more improvements + added tests (apache#3086)
1 parent 6063bba commit 7ef0c54

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;
@@ -87,38 +90,131 @@ void testDotAllPattern() throws Exception {
8790
}
8891

8992
@Test
90-
void testNoMsg() throws Exception {
91-
final RegexFilter filter = RegexFilter.createFilter(".* test .*", null, false, null, null);
93+
void testNoMsg() {
94+
95+
final RegexFilter filter =
96+
RegexFilter.newBuilder()
97+
.setRegex(".* test .*")
98+
.setUseRawMsg(false)
99+
.build();
100+
101+
assertNotNull(filter);
102+
92103
filter.start();
104+
93105
assertTrue(filter.isStarted());
94106
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Object) null, null));
95107
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, (Message) null, null));
96108
assertSame(Filter.Result.DENY, filter.filter(null, Level.DEBUG, null, null, (Object[]) null));
97109
}
98110

99111
@Test
100-
void testParameterizedMsg() throws Exception {
112+
void testParameterizedMsg() {
101113
final String msg = "params {} {}";
102114
final Object[] params = {"foo", "bar"};
103115

104116
// match against raw message
105-
final RegexFilter rawFilter = RegexFilter.createFilter(
106-
"params \\{\\} \\{\\}",
107-
null,
108-
true, // useRawMsg
109-
Result.ACCEPT,
110-
Result.DENY);
117+
final RegexFilter rawFilter =
118+
RegexFilter.newBuilder()
119+
.setRegex("params \\{\\} \\{\\}")
120+
.setUseRawMsg(true)
121+
.setOnMatch(Result.ACCEPT)
122+
.setOnMismatch(Result.DENY)
123+
.build();
124+
125+
assertNotNull(rawFilter);
126+
111127
final Result rawResult = rawFilter.filter(null, null, null, msg, params);
112128
assertThat(rawResult, equalTo(Result.ACCEPT));
113129

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

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;
@@ -44,9 +45,6 @@
4445
@Plugin(name = "RegexFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
4546
public final class RegexFilter extends AbstractFilter {
4647

47-
/** The regular-expression. */
48-
private final String regex;
49-
5048
/** The pattern compiled from the regular-expression. */
5149
private final Pattern pattern;
5250

@@ -62,13 +60,12 @@ private RegexFilter(final Builder builder) {
6260

6361
super(builder);
6462

65-
this.regex = builder.regex;
6663
this.useRawMessage = Boolean.TRUE.equals(builder.useRawMsg);
6764

6865
try {
69-
this.pattern = Pattern.compile(regex);
66+
this.pattern = Pattern.compile(builder.regex);
7067
} catch (final Exception ex) {
71-
throw new IllegalArgumentException("Unable to compile regular expression: '" + regex + "'.", ex);
68+
throw new IllegalArgumentException("Unable to compile regular expression: '" + builder.regex + "'.", ex);
7269
}
7370
}
7471

@@ -77,7 +74,7 @@ private RegexFilter(final Builder builder) {
7774
* @return the regular-expression (it may be an empty string but never {@code null})
7875
*/
7976
public String getRegex() {
80-
return this.regex;
77+
return this.pattern.pattern();
8178
}
8279

8380
/**
@@ -136,7 +133,7 @@ public Result filter(final LogEvent event) {
136133
* @param msg the message
137134
* @return the filter result
138135
*/
139-
private Result filter(final String msg) {
136+
public Result filter(final String msg) {
140137
if (msg == null) {
141138
return onMismatch;
142139
}
@@ -181,7 +178,7 @@ private String getMessageTextByType(final Message message) {
181178

182179
@Override
183180
public String toString() {
184-
return "useRawMessage=" + useRawMessage + ", regex=" + regex + ", pattern=" + pattern.toString();
181+
return "useRawMessage=" + useRawMessage + ", pattern=" + pattern.toString();
185182
}
186183

187184
/**
@@ -251,7 +248,11 @@ public Builder setUseRawMsg(final boolean useRawMsg) {
251248
*/
252249
@Override
253250
public boolean isValid() {
254-
return (regex != null);
251+
boolean valid = true;
252+
if (!isRegexValid()) {
253+
valid = false;
254+
}
255+
return valid;
255256
}
256257

257258
/**
@@ -273,6 +274,25 @@ public RegexFilter build() {
273274
return null;
274275
}
275276
}
277+
278+
/**
279+
* Validates the 'regex' attribute.
280+
* <p>
281+
* If the regular-expression is not set, or cannot be compiled to a valid pattern the validation will fail.
282+
* </p>
283+
* @return {@code true} if the regular-expression is valid; otherwise, {@code false}
284+
*/
285+
private boolean isRegexValid() {
286+
if (regex == null) {
287+
return false;
288+
}
289+
try {
290+
Pattern.compile(regex);
291+
} catch (final PatternSyntaxException ex) {
292+
return false;
293+
}
294+
return true;
295+
}
276296
}
277297

278298
/*
@@ -306,7 +326,7 @@ private RegexFilter(
306326
final Result onMatch,
307327
final Result onMismatch) {
308328
super(onMatch, onMismatch);
309-
this.regex = Objects.requireNonNull(regex, "The 'regex' argument must be provided for RegexFilter");
329+
Objects.requireNonNull(regex, "The 'regex' argument must be provided for RegexFilter");
310330
this.patternFlags = patternFlags == null ? new String[0] : patternFlags.clone();
311331
try {
312332
int flags = toPatternFlags(this.patternFlags);

0 commit comments

Comments
 (0)