@@ -51,38 +51,34 @@ public final class Grok {
51
51
52
52
private static final int MAX_TO_REGEX_ITERATIONS = 100_000 ; // sanity limit
53
53
54
- private final Map <String , String > patternBank ;
55
54
private final boolean namedCaptures ;
56
55
private final Regex compiledExpression ;
57
56
private final MatcherWatchdog matcherWatchdog ;
58
57
private final List <GrokCaptureConfig > captureConfig ;
59
58
60
- public Grok (Map < String , String > patternBank , String grokPattern , Consumer <String > logCallBack ) {
59
+ public Grok (PatternBank patternBank , String grokPattern , Consumer <String > logCallBack ) {
61
60
this (patternBank , grokPattern , true , MatcherWatchdog .noop (), logCallBack );
62
61
}
63
62
64
- public Grok (Map < String , String > patternBank , String grokPattern , MatcherWatchdog matcherWatchdog , Consumer <String > logCallBack ) {
63
+ public Grok (PatternBank patternBank , String grokPattern , MatcherWatchdog matcherWatchdog , Consumer <String > logCallBack ) {
65
64
this (patternBank , grokPattern , true , matcherWatchdog , logCallBack );
66
65
}
67
66
68
- Grok (Map < String , String > patternBank , String grokPattern , boolean namedCaptures , Consumer <String > logCallBack ) {
67
+ Grok (PatternBank patternBank , String grokPattern , boolean namedCaptures , Consumer <String > logCallBack ) {
69
68
this (patternBank , grokPattern , namedCaptures , MatcherWatchdog .noop (), logCallBack );
70
69
}
71
70
72
71
private Grok (
73
- Map < String , String > patternBank ,
72
+ PatternBank patternBank ,
74
73
String grokPattern ,
75
74
boolean namedCaptures ,
76
75
MatcherWatchdog matcherWatchdog ,
77
76
Consumer <String > logCallBack
78
77
) {
79
- this .patternBank = patternBank ;
80
78
this .namedCaptures = namedCaptures ;
81
79
this .matcherWatchdog = matcherWatchdog ;
82
80
83
- forbidCircularReferences ();
84
-
85
- String expression = toRegex (grokPattern );
81
+ String expression = toRegex (patternBank , grokPattern );
86
82
byte [] expressionBytes = expression .getBytes (StandardCharsets .UTF_8 );
87
83
this .compiledExpression = new Regex (
88
84
expressionBytes ,
@@ -100,78 +96,6 @@ private Grok(
100
96
this .captureConfig = List .copyOf (grokCaptureConfigs );
101
97
}
102
98
103
- /**
104
- * Checks whether patterns reference each other in a circular manner and if so fail with an exception
105
- *
106
- * In a pattern, anything between <code>%{</code> and <code>}</code> or <code>:</code> is considered
107
- * a reference to another named pattern. This method will navigate to all these named patterns and
108
- * check for a circular reference.
109
- */
110
- private void forbidCircularReferences () {
111
-
112
- // first ensure that the pattern bank contains no simple circular references (i.e., any pattern
113
- // containing an immediate reference to itself) as those can cause the remainder of this algorithm
114
- // to recurse infinitely
115
- for (Map .Entry <String , String > entry : patternBank .entrySet ()) {
116
- if (patternReferencesItself (entry .getValue (), entry .getKey ())) {
117
- throw new IllegalArgumentException ("circular reference in pattern [" + entry .getKey () + "][" + entry .getValue () + "]" );
118
- }
119
- }
120
-
121
- // next, recursively check any other pattern names referenced in each pattern
122
- for (Map .Entry <String , String > entry : patternBank .entrySet ()) {
123
- String name = entry .getKey ();
124
- String pattern = entry .getValue ();
125
- innerForbidCircularReferences (name , new ArrayList <>(), pattern );
126
- }
127
- }
128
-
129
- private void innerForbidCircularReferences (String patternName , List <String > path , String pattern ) {
130
- if (patternReferencesItself (pattern , patternName )) {
131
- String message ;
132
- if (path .isEmpty ()) {
133
- message = "circular reference in pattern [" + patternName + "][" + pattern + "]" ;
134
- } else {
135
- message = "circular reference in pattern ["
136
- + path .remove (path .size () - 1 )
137
- + "]["
138
- + pattern
139
- + "] back to pattern ["
140
- + patternName
141
- + "]" ;
142
- // add rest of the path:
143
- if (path .isEmpty () == false ) {
144
- message += " via patterns [" + String .join ("=>" , path ) + "]" ;
145
- }
146
- }
147
- throw new IllegalArgumentException (message );
148
- }
149
-
150
- // next check any other pattern names found in the pattern
151
- for (int i = pattern .indexOf ("%{" ); i != -1 ; i = pattern .indexOf ("%{" , i + 1 )) {
152
- int begin = i + 2 ;
153
- int bracketIndex = pattern .indexOf ('}' , begin );
154
- int columnIndex = pattern .indexOf (':' , begin );
155
- int end ;
156
- if (bracketIndex != -1 && columnIndex == -1 ) {
157
- end = bracketIndex ;
158
- } else if (columnIndex != -1 && bracketIndex == -1 ) {
159
- end = columnIndex ;
160
- } else if (bracketIndex != -1 && columnIndex != -1 ) {
161
- end = Math .min (bracketIndex , columnIndex );
162
- } else {
163
- throw new IllegalArgumentException ("pattern [" + pattern + "] has circular references to other pattern definitions" );
164
- }
165
- String otherPatternName = pattern .substring (begin , end );
166
- path .add (otherPatternName );
167
- innerForbidCircularReferences (patternName , path , patternBank .get (otherPatternName ));
168
- }
169
- }
170
-
171
- private static boolean patternReferencesItself (String pattern , String patternName ) {
172
- return pattern .contains ("%{" + patternName + "}" ) || pattern .contains ("%{" + patternName + ":" );
173
- }
174
-
175
99
private String groupMatch (String name , Region region , String pattern ) {
176
100
int number = GROK_PATTERN_REGEX .nameToBackrefNumber (
177
101
name .getBytes (StandardCharsets .UTF_8 ),
@@ -192,7 +116,7 @@ private String groupMatch(String name, Region region, String pattern) {
192
116
*
193
117
* @return named regex expression
194
118
*/
195
- protected String toRegex (String grokPattern ) {
119
+ protected String toRegex (PatternBank patternBank , String grokPattern ) {
196
120
StringBuilder res = new StringBuilder ();
197
121
for (int i = 0 ; i < MAX_TO_REGEX_ITERATIONS ; i ++) {
198
122
byte [] grokPatternBytes = grokPattern .getBytes (StandardCharsets .UTF_8 );
0 commit comments