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 childNode.getAttributes().putAll(sourceLoggerChild.getAttributes());
175 childNode.getChildren().addAll(sourceLoggerChild.getChildren());
176 targetNode.getChildren().add(childNode);
177 }
178 } else {
179 final Node childNode = new Node(loggerNode, sourceLoggerChild.getName(),
180 sourceLoggerChild.getType());
181 childNode.getAttributes().putAll(sourceLoggerChild.getAttributes());
182 childNode.getChildren().addAll(sourceLoggerChild.getChildren());
183 if (childNode.getName().equalsIgnoreCase("AppenderRef")) {
184 for (final Node targetChild : targetNode.getChildren()) {
185 if (isSameReference(targetChild, childNode)) {
186 targetNode.getChildren().remove(targetChild);
187 break;
188 }
189 }
190 } else {
191 for (final Node targetChild : targetNode.getChildren()) {
192 if (isSameName(targetChild, childNode)) {
193 targetNode.getChildren().remove(targetChild);
194 break;
195 }
196 }
197 }
198
199 targetNode.getChildren().add(childNode);
200 }
201 }
202 } else {
203 loggerNode.getAttributes().putAll(node.getAttributes());
204 loggerNode.getChildren().addAll(node.getChildren());
205 targetChildNode.getChildren().add(loggerNode);
206 }
207 }
208 isMerged = true;
209 break;
210 }
211 default: {
212 targetChildNode.getChildren().addAll(sourceChildNode.getChildren());
213 isMerged = true;
214 break;
215 }
216
217 }
218 }
219 if (!isMerged) {
220 if (sourceChildNode.getName().equalsIgnoreCase("Properties")) {
221 target.getChildren().add(0, sourceChildNode);
222 } else {
223 target.getChildren().add(sourceChildNode);
224 }
225 }
226 }
227 }
228
229 private Node getLoggerNode(final Node parentNode, final String name) {
230 for (final Node node : parentNode.getChildren()) {
231 final String nodeName = node.getAttributes().get(NAME);
232 if (name == null && nodeName == null) {
233 return node;
234 }
235 if (nodeName != null && nodeName.equals(name)) {
236 return node;
237 }
238 }
239 return null;
240 }
241
242 private void updateFilterNode(final Node target, final Node targetChildNode, final Node sourceChildNode,
243 final PluginManager pluginManager) {
244 if (CompositeFilter.class.isAssignableFrom(targetChildNode.getType().getPluginClass())) {
245 final Node node = new Node(targetChildNode, sourceChildNode.getName(), sourceChildNode.getType());
246 node.getChildren().addAll(sourceChildNode.getChildren());
247 node.getAttributes().putAll(sourceChildNode.getAttributes());
248 targetChildNode.getChildren().add(node);
249 } else {
250 final PluginType pluginType = pluginManager.getPluginType(FILTERS);
251 final Node filtersNode = new Node(targetChildNode, FILTERS, pluginType);
252 final Node node = new Node(filtersNode, sourceChildNode.getName(), sourceChildNode.getType());
253 node.getAttributes().putAll(sourceChildNode.getAttributes());
254 final List<Node> children = filtersNode.getChildren();
255 children.add(targetChildNode);
256 children.add(node);
257 final List<Node> nodes = target.getChildren();
258 nodes.remove(targetChildNode);
259 nodes.add(filtersNode);
260 }
261 }
262
263 private boolean isFilterNode(final Node node) {
264 return Filter.class.isAssignableFrom(node.getType().getPluginClass());
265 }
266
267 private boolean isSameName(final Node node1, final Node node2) {
268 final String value = node1.getAttributes().get(NAME);
269 return value != null && value.toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase());
270 }
271
272 private boolean isSameReference(final Node node1, final Node node2) {
273 final String value = node1.getAttributes().get(REF);
274 return value != null && value.toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase());
275 }
276 }