1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.config.composite;
18
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Objects;
23
24 import org.apache.logging.log4j.Level;
25 import org.apache.logging.log4j.core.Filter;
26 import org.apache.logging.log4j.core.config.AbstractConfiguration;
27 import org.apache.logging.log4j.core.config.Node;
28 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
29 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
30 import org.apache.logging.log4j.core.filter.CompositeFilter;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class DefaultMergeStrategy implements MergeStrategy {
56
57 private static final String APPENDERS = "appenders";
58 private static final String PROPERTIES = "properties";
59 private static final String LOGGERS = "loggers";
60 private static final String SCRIPTS = "scripts";
61 private static final String FILTERS = "filters";
62 private static final String STATUS = "status";
63 private static final String NAME = "name";
64 private static final String REF = "ref";
65
66
67
68
69
70
71 @Override
72 public void mergeRootProperties(final Node rootNode, final AbstractConfiguration configuration) {
73 for (final Map.Entry<String, String> attribute : configuration.getRootNode().getAttributes().entrySet()) {
74 boolean isFound = false;
75 for (final Map.Entry<String, String> targetAttribute : rootNode.getAttributes().entrySet()) {
76 if (targetAttribute.getKey().equalsIgnoreCase(attribute.getKey())) {
77 if (attribute.getKey().equalsIgnoreCase(STATUS)) {
78 final Level targetLevel = Level.getLevel(targetAttribute.getValue().toUpperCase());
79 final Level sourceLevel = Level.getLevel(attribute.getValue().toUpperCase());
80 if (targetLevel != null && sourceLevel != null) {
81 if (sourceLevel.isLessSpecificThan(targetLevel)) {
82 targetAttribute.setValue(attribute.getValue());
83 }
84 } else
85 if (sourceLevel != null) {
86 targetAttribute.setValue(attribute.getValue());
87 }
88 } else {
89 if (attribute.getKey().equalsIgnoreCase("monitorInterval")) {
90 final int sourceInterval = Integer.parseInt(attribute.getValue());
91 final int targetInterval = Integer.parseInt(targetAttribute.getValue());
92 if (targetInterval == 0 || sourceInterval < targetInterval) {
93 targetAttribute.setValue(attribute.getValue());
94 }
95 } else {
96 targetAttribute.setValue(attribute.getValue());
97 }
98 }
99 isFound = true;
100 }
101 }
102 if (!isFound) {
103 rootNode.getAttributes().put(attribute.getKey(), attribute.getValue());
104 }
105 }
106 }
107
108
109
110
111
112
113
114
115 @Override
116 public void mergConfigurations(final Node target, final Node source, final PluginManager pluginManager) {
117 for (final Node sourceChildNode : source.getChildren()) {
118 final boolean isFilter = isFilterNode(sourceChildNode);
119 boolean isMerged = false;
120 for (final Node targetChildNode : target.getChildren()) {
121 if (isFilter) {
122 if (isFilterNode(targetChildNode)) {
123 updateFilterNode(target, targetChildNode, sourceChildNode, pluginManager);
124 isMerged = true;
125 break;
126 }
127 continue;
128 }
129
130 if (!targetChildNode.getName().equalsIgnoreCase(sourceChildNode.getName())) {
131 continue;
132 }
133
134 switch (targetChildNode.getName().toLowerCase()) {
135 case PROPERTIES:
136 case SCRIPTS:
137 case APPENDERS: {
138 for (final Node node : sourceChildNode.getChildren()) {
139 for (final Node targetNode : targetChildNode.getChildren()) {
140 if (Objects.equals(targetNode.getAttributes().get(NAME), node.getAttributes().get(NAME))) {
141 targetChildNode.getChildren().remove(targetNode);
142 break;
143 }
144 }
145 targetChildNode.getChildren().add(node);
146 }
147 isMerged = true;
148 break;
149 }
150 case LOGGERS: {
151 final Map<String, Node> targetLoggers = new HashMap<>();
152 for (final Node node : targetChildNode.getChildren()) {
153 targetLoggers.put(node.getName(), node);
154 }
155 for (final Node node : sourceChildNode.getChildren()) {
156 final Node targetNode = getLoggerNode(targetChildNode, node.getAttributes().get(NAME));
157 final Node loggerNode = new Node(targetChildNode, node.getName(), node.getType());
158 if (targetNode != null) {
159 targetNode.getAttributes().putAll(node.getAttributes());
160 for (final Node sourceLoggerChild : node.getChildren()) {
161 if (isFilterNode(sourceLoggerChild)) {
162 boolean foundFilter = false;
163 for (final Node targetChild : targetNode.getChildren()) {
164 if (isFilterNode(targetChild)) {
165 updateFilterNode(loggerNode, targetChild, sourceLoggerChild,
166 pluginManager);
167 foundFilter = true;
168 break;
169 }
170 }
171 if (!foundFilter) {
172 final Node childNode = new Node(loggerNode, sourceLoggerChild.getName(),
173 sourceLoggerChild.getType());
174 targetNode.getChildren().add(childNode);
175 }
176 } else {
177 final Node childNode = new Node(loggerNode, sourceLoggerChild.getName(),
178 sourceLoggerChild.getType());
179 childNode.getAttributes().putAll(sourceLoggerChild.getAttributes());
180 childNode.getChildren().addAll(sourceLoggerChild.getChildren());
181 if (childNode.getName().equalsIgnoreCase("AppenderRef")) {
182 for (final Node targetChild : targetNode.getChildren()) {
183 if (isSameReference(targetChild, childNode)) {
184 targetNode.getChildren().remove(targetChild);
185 break;
186 }
187 }
188 } else {
189 for (final Node targetChild : targetNode.getChildren()) {
190 if (isSameName(targetChild, childNode)) {
191 targetNode.getChildren().remove(targetChild);
192 break;
193 }
194 }
195 }
196
197 targetNode.getChildren().add(childNode);
198 }
199 }
200 } else {
201 loggerNode.getAttributes().putAll(node.getAttributes());
202 loggerNode.getChildren().addAll(node.getChildren());
203 targetChildNode.getChildren().add(loggerNode);
204 }
205 }
206 isMerged = true;
207 break;
208 }
209 default: {
210 targetChildNode.getChildren().addAll(sourceChildNode.getChildren());
211 isMerged = true;
212 break;
213 }
214
215 }
216 }
217 if (!isMerged) {
218 if (sourceChildNode.getName().equalsIgnoreCase("Properties")) {
219 target.getChildren().add(0, sourceChildNode);
220 } else {
221 target.getChildren().add(sourceChildNode);
222 }
223 }
224 }
225 }
226
227 private Node getLoggerNode(final Node parentNode, final String name) {
228 for (final Node node : parentNode.getChildren()) {
229 final String nodeName = node.getAttributes().get(NAME);
230 if (name == null && nodeName == null) {
231 return node;
232 }
233 if (nodeName != null && nodeName.equals(name)) {
234 return node;
235 }
236 }
237 return null;
238 }
239
240 private void updateFilterNode(final Node target, final Node targetChildNode, final Node sourceChildNode,
241 final PluginManager pluginManager) {
242 if (CompositeFilter.class.isAssignableFrom(targetChildNode.getType().getPluginClass())) {
243 final Node node = new Node(targetChildNode, sourceChildNode.getName(), sourceChildNode.getType());
244 node.getChildren().addAll(sourceChildNode.getChildren());
245 node.getAttributes().putAll(sourceChildNode.getAttributes());
246 targetChildNode.getChildren().add(node);
247 } else {
248 final PluginType pluginType = pluginManager.getPluginType(FILTERS);
249 final Node filtersNode = new Node(targetChildNode, FILTERS, pluginType);
250 final Node node = new Node(filtersNode, sourceChildNode.getName(), sourceChildNode.getType());
251 node.getAttributes().putAll(sourceChildNode.getAttributes());
252 final List<Node> children = filtersNode.getChildren();
253 children.add(targetChildNode);
254 children.add(node);
255 final List<Node> nodes = target.getChildren();
256 nodes.remove(targetChildNode);
257 nodes.add(filtersNode);
258 }
259 }
260
261 private boolean isFilterNode(final Node node) {
262 return Filter.class.isAssignableFrom(node.getType().getPluginClass());
263 }
264
265 private boolean isSameName(final Node node1, final Node node2) {
266 final String value = node1.getAttributes().get(NAME);
267 return value != null && value.toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase());
268 }
269
270 private boolean isSameReference(final Node node1, final Node node2) {
271 final String value = node1.getAttributes().get(REF);
272 return value != null && value.toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase());
273 }
274 }