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