1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.joran.spi;
15
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.function.Supplier;
21
22 import ch.qos.logback.core.Context;
23 import ch.qos.logback.core.joran.action.Action;
24 import ch.qos.logback.core.spi.ContextAwareBase;
25 import ch.qos.logback.core.util.OptionHelper;
26
27
28
29
30
31
32
33
34 public class SimpleRuleStore extends ContextAwareBase implements RuleStore {
35
36 static String KLEENE_STAR = "*";
37
38
39 HashMap<ElementSelector, Supplier<Action>> rules = new HashMap<>();
40
41 List<String> transparentPathParts = new ArrayList<>(2);
42 Map<String, String> pathPartsMapForRenaming = new HashMap<>(2);
43
44 public SimpleRuleStore(Context context) {
45 setContext(context);
46 }
47
48
49 public void addTransparentPathPart(String pathPart) {
50 if (pathPart == null)
51 throw new IllegalArgumentException("pathPart cannot be null");
52
53 pathPart = pathPart.trim();
54
55 if (pathPart.isEmpty())
56 throw new IllegalArgumentException("pathPart cannot be empty or to consist of only spaces");
57
58 if (pathPart.contains("/"))
59 throw new IllegalArgumentException("pathPart cannot contain '/', i.e. the forward slash character");
60
61 transparentPathParts.add(pathPart);
62
63 }
64
65
66
67
68
69
70
71
72 @Override
73 public void addPathPathMapping(String originalName, String modifiedName) {
74 pathPartsMapForRenaming.put(originalName, modifiedName);
75 }
76
77
78
79
80
81
82 public void addRule(ElementSelector elementSelector, Supplier<Action> actionSupplier) {
83
84 Supplier<Action> existing = rules.get(elementSelector);
85
86 if (existing == null) {
87 rules.put(elementSelector, actionSupplier);
88 } else {
89 throw new IllegalStateException(elementSelector.toString() + " already has an associated action supplier");
90 }
91 }
92
93 public void addRule(ElementSelector elementSelector, String actionClassName) {
94 Action action = null;
95
96 try {
97 action = (Action) OptionHelper.instantiateByClassName(actionClassName, Action.class, context);
98 } catch (Exception e) {
99 addError("Could not instantiate class [" + actionClassName + "]", e);
100 }
101 if (action != null) {
102
103 }
104 }
105
106
107
108
109
110
111
112
113 public Supplier<Action> matchActions(ElementPath elementPath) {
114
115 Supplier<Action> actionSupplier = internalMatchAction(elementPath);
116 if(actionSupplier != null) {
117 return actionSupplier;
118 }
119
120 actionSupplier = matchActionsWithoutTransparentParts(elementPath);
121 if(actionSupplier != null) {
122 return actionSupplier;
123 }
124
125 return matchActionsWithRenamedParts(elementPath);
126
127 }
128
129 private Supplier<Action> matchActionsWithoutTransparentParts(ElementPath elementPath) {
130 ElementPath cleanedElementPath = removeTransparentPathParts(elementPath);
131 return internalMatchAction(cleanedElementPath);
132 }
133
134 private Supplier<Action> matchActionsWithRenamedParts(ElementPath elementPath) {
135 ElementPath renamedElementPath = renamePathParts(elementPath);
136 return internalMatchAction(renamedElementPath);
137 }
138
139 private Supplier<Action> internalMatchAction(ElementPath elementPath) {
140 Supplier<Action> actionSupplier;
141
142 if ((actionSupplier = fullPathMatch(elementPath)) != null) {
143 return actionSupplier;
144 } else if ((actionSupplier = suffixMatch(elementPath)) != null) {
145 return actionSupplier;
146 } else if ((actionSupplier = prefixMatch(elementPath)) != null) {
147 return actionSupplier;
148 } else if ((actionSupplier = middleMatch(elementPath)) != null) {
149 return actionSupplier;
150 } else {
151 return null;
152 }
153 }
154
155 ElementPath removeTransparentPathParts(ElementPath originalElementPath) {
156
157 List<String> preservedElementList = new ArrayList<>(originalElementPath.partList.size());
158
159 for (String part : originalElementPath.partList) {
160 boolean shouldKeep = transparentPathParts.stream().noneMatch(p -> p.equalsIgnoreCase(part));
161 if (shouldKeep)
162 preservedElementList.add(part);
163 }
164
165 return new ElementPath(preservedElementList);
166
167 }
168
169
170 ElementPath renamePathParts(ElementPath originalElementPath) {
171
172 List<String> result = new ArrayList<>(originalElementPath.partList.size());
173
174 for (String part : originalElementPath.partList) {
175 String modifiedName = pathPartsMapForRenaming.getOrDefault(part, part);
176 result.add(modifiedName);
177 }
178
179 return new ElementPath(result);
180 }
181
182
183 Supplier<Action> fullPathMatch(ElementPath elementPath) {
184 for (ElementSelector selector : rules.keySet()) {
185 if (selector.fullPathMatch(elementPath))
186 return rules.get(selector);
187 }
188 return null;
189 }
190
191
192 Supplier<Action> suffixMatch(ElementPath elementPath) {
193 int max = 0;
194 ElementSelector longestMatchingElementSelector = null;
195
196 for (ElementSelector selector : rules.keySet()) {
197 if (isSuffixPattern(selector)) {
198 int r = selector.getTailMatchLength(elementPath);
199 if (r > max) {
200 max = r;
201 longestMatchingElementSelector = selector;
202 }
203 }
204 }
205
206 if (longestMatchingElementSelector != null) {
207 return rules.get(longestMatchingElementSelector);
208 } else {
209 return null;
210 }
211 }
212
213 private boolean isSuffixPattern(ElementSelector p) {
214 return (p.size() > 1) && p.get(0).equals(KLEENE_STAR);
215 }
216
217 Supplier<Action> prefixMatch(ElementPath elementPath) {
218 int max = 0;
219 ElementSelector longestMatchingElementSelector = null;
220
221 for (ElementSelector selector : rules.keySet()) {
222 String last = selector.peekLast();
223 if (isKleeneStar(last)) {
224 int r = selector.getPrefixMatchLength(elementPath);
225
226 if ((r == selector.size() - 1) && (r > max)) {
227 max = r;
228 longestMatchingElementSelector = selector;
229 }
230 }
231 }
232
233 if (longestMatchingElementSelector != null) {
234 return rules.get(longestMatchingElementSelector);
235 } else {
236 return null;
237 }
238 }
239
240 private boolean isKleeneStar(String last) {
241 return KLEENE_STAR.equals(last);
242 }
243
244 Supplier<Action> middleMatch(ElementPath path) {
245
246 int max = 0;
247 ElementSelector longestMatchingElementSelector = null;
248
249 for (ElementSelector selector : rules.keySet()) {
250 String last = selector.peekLast();
251 String first = null;
252 if (selector.size() > 1) {
253 first = selector.get(0);
254 }
255 if (isKleeneStar(last) && isKleeneStar(first)) {
256 List<String> copyOfPartList = selector.getCopyOfPartList();
257 if (copyOfPartList.size() > 2) {
258 copyOfPartList.remove(0);
259 copyOfPartList.remove(copyOfPartList.size() - 1);
260 }
261
262 int r = 0;
263 ElementSelector clone = new ElementSelector(copyOfPartList);
264 if (clone.isContainedIn(path)) {
265 r = clone.size();
266 }
267 if (r > max) {
268 max = r;
269 longestMatchingElementSelector = selector;
270 }
271 }
272 }
273
274 if (longestMatchingElementSelector != null) {
275 return rules.get(longestMatchingElementSelector);
276 } else {
277 return null;
278 }
279 }
280
281 public String toString() {
282 final String TAB = " ";
283
284 StringBuilder retValue = new StringBuilder();
285
286 retValue.append("SimpleRuleStore ( ").append("rules = ").append(this.rules).append(TAB).append(" )");
287
288 return retValue.toString();
289 }
290
291 }