1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.joran.sanity;
15
16 import ch.qos.logback.core.model.AppenderModel;
17 import ch.qos.logback.core.model.Model;
18 import ch.qos.logback.core.spi.ContextAwareBase;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.stream.Collectors;
23
24 public class AppenderWithinAppenderSanityChecker extends ContextAwareBase implements SanityChecker {
25
26 static public String NESTED_APPENDERS_WARNING = "As of logback version 1.3, nested appenders are not allowed.";
27
28 @Override
29 public void check(Model model) {
30 if (model == null)
31 return;
32
33 List<Model> appenderModels = new ArrayList<>();
34 deepFindAllModelsOfType(AppenderModel.class, appenderModels, model);
35
36 List<Pair<Model, Model>> nestedPairs = deepFindNestedSubModelsOfType(AppenderModel.class, appenderModels);
37
38 List<Pair<Model, Model>> filteredNestedPairs = nestedPairs.stream().filter(pair -> !isSiftingAppender(pair.first)).collect(Collectors.toList());
39
40 if(filteredNestedPairs.isEmpty()) {
41 return;
42 }
43 addWarn(NESTED_APPENDERS_WARNING);
44 for(Pair<Model, Model> pair: filteredNestedPairs) {
45 addWarn("Appender at line "+pair.first.getLineNumber() + " contains a nested appender at line "+pair.second.getLineNumber());
46 }
47 }
48
49 private boolean isSiftingAppender(Model first) {
50 if(first instanceof AppenderModel) {
51 AppenderModel appenderModel = (AppenderModel) first;
52 String classname = appenderModel.getClassName();
53 if(classname == null)
54 return false;
55 return appenderModel.getClassName().contains("SiftingAppender");
56 }
57 return false;
58 }
59
60 }