1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.spi;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.NoSuchElementException;
25
26
27
28
29
30
31
32 public class DefaultThreadContextStack implements ThreadContextStack {
33
34 private static final long serialVersionUID = 5050501L;
35
36 private static ThreadLocal<List<String>> stack = new ThreadLocal<List<String>>();
37
38 private final boolean useStack;
39
40 public DefaultThreadContextStack(final boolean useStack) {
41 this.useStack = useStack;
42 }
43
44 @Override
45 public String pop() {
46 if (!useStack) {
47 return "";
48 }
49 final List<String> list = stack.get();
50 if (list == null || list.size() == 0) {
51 throw new NoSuchElementException("The ThreadContext stack is empty");
52 }
53 final List<String> copy = new ArrayList<String>(list);
54 final int last = copy.size() - 1;
55 final String result = copy.remove(last);
56 stack.set(Collections.unmodifiableList(copy));
57 return result;
58 }
59
60 @Override
61 public String peek() {
62 final List<String> list = stack.get();
63 if (list == null || list.size() == 0) {
64 return null;
65 }
66 final int last = list.size() - 1;
67 return list.get(last);
68 }
69
70 @Override
71 public void push(final String message) {
72 if (!useStack) {
73 return;
74 }
75 add(message);
76 }
77
78 @Override
79 public int getDepth() {
80 final List<String> list = stack.get();
81 return list == null ? 0 : list.size();
82 }
83
84 @Override
85 public List<String> asList() {
86 final List<String> list = stack.get();
87 if (list == null) {
88 return Collections.emptyList();
89 }
90 return list;
91 }
92
93 @Override
94 public void trim(final int depth) {
95 if (depth < 0) {
96 throw new IllegalArgumentException(
97 "Maximum stack depth cannot be negative");
98 }
99 final List<String> list = stack.get();
100 if (list == null) {
101 return;
102 }
103 final List<String> copy = new ArrayList<String>();
104 final int count = Math.min(depth, list.size());
105 for (int i = 0; i < count; i++) {
106 copy.add(list.get(i));
107 }
108 stack.set(copy);
109 }
110
111 @Override
112 public ThreadContextStack copy() {
113 List<String> result = null;
114 if (!useStack || (result = stack.get()) == null) {
115 return new MutableThreadContextStack(new ArrayList<String>());
116 }
117 return new MutableThreadContextStack(result);
118 }
119
120 @Override
121 public void clear() {
122 stack.remove();
123 }
124
125 @Override
126 public int size() {
127 final List<String> result = stack.get();
128 return result == null ? 0 : result.size();
129 }
130
131 @Override
132 public boolean isEmpty() {
133 final List<String> result = stack.get();
134 return result == null || result.isEmpty();
135 }
136
137 @Override
138 public boolean contains(final Object o) {
139 final List<String> result = stack.get();
140 return result != null && result.contains(o);
141 }
142
143 @Override
144 public Iterator<String> iterator() {
145 final List<String> immutable = stack.get();
146 if (immutable == null) {
147 final List<String> empty = Collections.emptyList();
148 return empty.iterator();
149 }
150 return immutable.iterator();
151 }
152
153 @Override
154 public Object[] toArray() {
155 final List<String> result = stack.get();
156 if (result == null) {
157 return new String[0];
158 }
159 return result.toArray(new Object[result.size()]);
160 }
161
162 @Override
163 public <T> T[] toArray(final T[] ts) {
164 final List<String> result = stack.get();
165 if (result == null) {
166 if (ts.length > 0) {
167 ts[0] = null;
168 }
169 return ts;
170 }
171 return result.toArray(ts);
172 }
173
174 @Override
175 public boolean add(final String s) {
176 if (!useStack) {
177 return false;
178 }
179 final List<String> list = stack.get();
180 final List<String> copy = list == null ? new ArrayList<String>()
181 : new ArrayList<String>(list);
182 copy.add(s);
183 stack.set(Collections.unmodifiableList(copy));
184 return true;
185 }
186
187 @Override
188 public boolean remove(final Object o) {
189 if (!useStack) {
190 return false;
191 }
192 final List<String> list = stack.get();
193 if (list == null || list.size() == 0) {
194 return false;
195 }
196 final List<String> copy = new ArrayList<String>(list);
197 final boolean result = copy.remove(o);
198 stack.set(Collections.unmodifiableList(copy));
199 return result;
200 }
201
202 @Override
203 public boolean containsAll(final Collection<?> objects) {
204 if (objects.isEmpty()) {
205 return true;
206
207 }
208 final List<String> list = stack.get();
209 return list != null && list.containsAll(objects);
210 }
211
212 @Override
213 public boolean addAll(final Collection<? extends String> strings) {
214 if (!useStack || strings.isEmpty()) {
215 return false;
216 }
217 final List<String> list = stack.get();
218 final List<String> copy = list == null ? new ArrayList<String>()
219 : new ArrayList<String>(list);
220 copy.addAll(strings);
221 stack.set(Collections.unmodifiableList(copy));
222 return true;
223 }
224
225 @Override
226 public boolean removeAll(final Collection<?> objects) {
227 if (!useStack || objects.isEmpty()) {
228 return false;
229 }
230 final List<String> list = stack.get();
231 if (list == null || list.isEmpty()) {
232 return false;
233 }
234 final List<String> copy = new ArrayList<String>(list);
235 final boolean result = copy.removeAll(objects);
236 stack.set(Collections.unmodifiableList(copy));
237 return result;
238 }
239
240 @Override
241 public boolean retainAll(final Collection<?> objects) {
242 if (!useStack || objects.isEmpty()) {
243 return false;
244 }
245 final List<String> list = stack.get();
246 if (list == null || list.isEmpty()) {
247 return false;
248 }
249 final List<String> copy = new ArrayList<String>(list);
250 final boolean result = copy.retainAll(objects);
251 stack.set(Collections.unmodifiableList(copy));
252 return result;
253 }
254
255 @Override
256 public String toString() {
257 final List<String> list = stack.get();
258 return list == null ? "[]" : list.toString();
259 }
260 }