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