1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j;
18
19 import java.util.Arrays;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.ConcurrentMap;
22
23
24
25
26 public final class MarkerManager {
27
28 private static final ConcurrentMap<String, Marker> MARKERS = new ConcurrentHashMap<>();
29
30 private MarkerManager() {
31
32 }
33
34
35
36
37 public static void clear() {
38 MARKERS.clear();
39 }
40
41
42
43
44
45
46
47
48 public static boolean exists(final String key) {
49 return MARKERS.containsKey(key);
50 }
51
52
53
54
55
56
57
58
59 public static Marker getMarker(final String name) {
60 MARKERS.putIfAbsent(name, new Log4jMarker(name));
61 return MARKERS.get(name);
62 }
63
64
65
66
67
68
69
70
71
72
73 @Deprecated
74 public static Marker getMarker(final String name, final String parent) {
75 final Marker parentMarker = MARKERS.get(parent);
76 if (parentMarker == null) {
77 throw new IllegalArgumentException("Parent Marker " + parent + " has not been defined");
78 }
79 @SuppressWarnings("deprecation")
80 final Marker marker = getMarker(name, parentMarker);
81 return marker;
82 }
83
84
85
86
87
88
89
90
91
92
93 @Deprecated
94 public static Marker getMarker(final String name, final Marker parent) {
95 MARKERS.putIfAbsent(name, new Log4jMarker(name));
96 return MARKERS.get(name).addParents(parent);
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110 public static class Log4jMarker implements Marker {
111
112 private static final long serialVersionUID = 100L;
113
114 private final String name;
115
116 private volatile Marker[] parents;
117
118
119
120
121 @SuppressWarnings("unused")
122 private Log4jMarker() {
123 this.name = null;
124 this.parents = null;
125 }
126
127
128
129
130
131
132
133 public Log4jMarker(final String name) {
134 if (name == null) {
135
136
137 throw new IllegalArgumentException("Marker name cannot be null.");
138 }
139 this.name = name;
140 this.parents = null;
141 }
142
143
144
145 @Override
146 public synchronized Marker addParents(final Marker... parentMarkers) {
147 if (parentMarkers == null) {
148 throw new IllegalArgumentException("A parent marker must be specified");
149 }
150
151
152 final Marker[] localParents = this.parents;
153
154 int count = 0;
155 int size = parentMarkers.length;
156 if (localParents != null) {
157 for (final Marker parent : parentMarkers) {
158 if (!(contains(parent, localParents) || parent.isInstanceOf(this))) {
159 ++count;
160 }
161 }
162 if (count == 0) {
163 return this;
164 }
165 size = localParents.length + count;
166 }
167 final Marker[] markers = new Marker[size];
168 if (localParents != null) {
169
170
171 System.arraycopy(localParents, 0, markers, 0, localParents.length);
172 }
173 int index = localParents == null ? 0 : localParents.length;
174 for (final Marker parent : parentMarkers) {
175 if (localParents == null || !(contains(parent, localParents) || parent.isInstanceOf(this))) {
176 markers[index++] = parent;
177 }
178 }
179 this.parents = markers;
180 return this;
181 }
182
183 @Override
184 public synchronized boolean remove(final Marker parent) {
185 if (parent == null) {
186 throw new IllegalArgumentException("A parent marker must be specified");
187 }
188 final Marker[] localParents = this.parents;
189 if (localParents == null) {
190 return false;
191 }
192 final int localParentsLength = localParents.length;
193 if (localParentsLength == 1) {
194 if (localParents[0].equals(parent)) {
195 parents = null;
196 return true;
197 }
198 return false;
199 }
200 int index = 0;
201 final Marker[] markers = new Marker[localParentsLength - 1];
202
203 for (int i = 0; i < localParentsLength; i++) {
204 final Marker marker = localParents[i];
205 if (!marker.equals(parent)) {
206 if (index == localParentsLength - 1) {
207
208 return false;
209 }
210 markers[index++] = marker;
211 }
212 }
213 parents = markers;
214 return true;
215 }
216
217 @Override
218 public Marker setParents(final Marker... markers) {
219 if (markers == null || markers.length == 0) {
220 this.parents = null;
221 } else {
222 final Marker[] array = new Marker[markers.length];
223 System.arraycopy(markers, 0, array, 0, markers.length);
224 this.parents = array;
225 }
226 return this;
227 }
228
229 @Override
230 public String getName() {
231 return this.name;
232 }
233
234 @Override
235 public Marker[] getParents() {
236 if (this.parents == null) {
237 return null;
238 }
239 return Arrays.copyOf(this.parents, this.parents.length);
240 }
241
242 @Override
243 public boolean hasParents() {
244 return this.parents != null;
245 }
246
247 @Override
248 public boolean isInstanceOf(final Marker marker) {
249 if (marker == null) {
250 throw new IllegalArgumentException("A marker parameter is required");
251 }
252 if (this == marker) {
253 return true;
254 }
255 final Marker[] localParents = parents;
256 if (localParents != null) {
257
258 final int localParentsLength = localParents.length;
259 if (localParentsLength == 1) {
260 return checkParent(localParents[0], marker);
261 }
262 if (localParentsLength == 2) {
263 return checkParent(localParents[0], marker) || checkParent(localParents[1], marker);
264 }
265
266 for (int i = 0; i < localParentsLength; i++) {
267 final Marker localParent = localParents[i];
268 if (checkParent(localParent, marker)) {
269 return true;
270 }
271 }
272 }
273 return false;
274 }
275
276 @Override
277 public boolean isInstanceOf(final String markerName) {
278 if (markerName == null) {
279 throw new IllegalArgumentException("A marker name is required");
280 }
281 if (markerName.equals(this.getName())) {
282 return true;
283 }
284
285 final Marker marker = MARKERS.get(markerName);
286 if (marker == null) {
287 return false;
288 }
289 final Marker[] localParents = parents;
290 if (localParents != null) {
291 final int localParentsLength = localParents.length;
292 if (localParentsLength == 1) {
293 return checkParent(localParents[0], marker);
294 }
295 if (localParentsLength == 2) {
296 return checkParent(localParents[0], marker) || checkParent(localParents[1], marker);
297 }
298
299 for (int i = 0; i < localParentsLength; i++) {
300 final Marker localParent = localParents[i];
301 if (checkParent(localParent, marker)) {
302 return true;
303 }
304 }
305 }
306
307 return false;
308 }
309
310 private static boolean checkParent(final Marker parent, final Marker marker) {
311 if (parent == marker) {
312 return true;
313 }
314 final Marker[] localParents = parent instanceof Log4jMarker ? ((Log4jMarker) parent).parents : parent
315 .getParents();
316 if (localParents != null) {
317 final int localParentsLength = localParents.length;
318 if (localParentsLength == 1) {
319 return checkParent(localParents[0], marker);
320 }
321 if (localParentsLength == 2) {
322 return checkParent(localParents[0], marker) || checkParent(localParents[1], marker);
323 }
324
325 for (int i = 0; i < localParentsLength; i++) {
326 final Marker localParent = localParents[i];
327 if (checkParent(localParent, marker)) {
328 return true;
329 }
330 }
331 }
332 return false;
333 }
334
335
336
337
338 private static boolean contains(final Marker parent, final Marker... localParents) {
339
340
341 for (int i = 0, localParentsLength = localParents.length; i < localParentsLength; i++) {
342 final Marker marker = localParents[i];
343 if (marker == parent) {
344 return true;
345 }
346 }
347 return false;
348 }
349
350 @Override
351 public boolean equals(final Object o) {
352 if (this == o) {
353 return true;
354 }
355 if (o == null || !(o instanceof Marker)) {
356 return false;
357 }
358 final Marker marker = (Marker) o;
359 return name.equals(marker.getName());
360 }
361
362 @Override
363 public int hashCode() {
364 return name.hashCode();
365 }
366
367 @Override
368 public String toString() {
369
370 final StringBuilder sb = new StringBuilder(name);
371 final Marker[] localParents = parents;
372 if (localParents != null) {
373 addParentInfo(sb, localParents);
374 }
375 return sb.toString();
376 }
377
378 private static void addParentInfo(final StringBuilder sb, final Marker... parents) {
379 sb.append("[ ");
380 boolean first = true;
381
382 for (int i = 0, parentsLength = parents.length; i < parentsLength; i++) {
383 final Marker marker = parents[i];
384 if (!first) {
385 sb.append(", ");
386 }
387 first = false;
388 sb.append(marker.getName());
389 final Marker[] p = marker instanceof Log4jMarker ? ((Log4jMarker) marker).parents : marker.getParents();
390 if (p != null) {
391 addParentInfo(sb, p);
392 }
393 }
394 sb.append(" ]");
395 }
396 }
397
398 }