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 final boolean useStack;
37 private static ThreadLocal<List<String>> stack = new ThreadLocal<List<String>>();
38
39 public DefaultThreadContextStack(boolean useStack) {
40 this.useStack = useStack;
41 }
42
43 public String pop() {
44 if (!useStack) {
45 return "";
46 }
47 final List<String> list = stack.get();
48 if (list == null || list.size() == 0) {
49 throw new NoSuchElementException("The ThreadContext stack is empty");
50 }
51 final List<String> copy = new ArrayList<String>(list);
52 final int last = copy.size() - 1;
53 final String result = copy.remove(last);
54 stack.set(Collections.unmodifiableList(copy));
55 return result;
56 }
57
58 public String peek() {
59 final List<String> list = stack.get();
60 if (list == null || list.size() == 0) {
61 return null;
62 }
63 final int last = list.size() - 1;
64 return list.get(last);
65 }
66
67 public void push(final String message) {
68 if (!useStack) {
69 return;
70 }
71 add(message);
72 }
73
74 public int getDepth() {
75 final List<String> list = stack.get();
76 return list == null ? 0 : list.size();
77 }
78
79 public List<String> asList() {
80 final List<String> list = stack.get();
81 if (list == null) {
82 return Collections.emptyList();
83 }
84 return list;
85 }
86
87 public void trim(final int depth) {
88 if (depth < 0) {
89 throw new IllegalArgumentException(
90 "Maximum stack depth cannot be negative");
91 }
92 final List<String> list = stack.get();
93 if (list == null) {
94 return;
95 }
96 final List<String> copy = new ArrayList<String>();
97 int count = Math.min(depth, list.size());
98 for(int i = 0; i < count; i++) {
99 copy.add(list.get(i));
100 }
101 stack.set(copy);
102 }
103
104 public ThreadContextStack copy() {
105 List<String> result = null;
106 if (!useStack || (result = stack.get()) == null) {
107 return new MutableThreadContextStack(new ArrayList<String>());
108 }
109 return new MutableThreadContextStack(result);
110 }
111
112 public void clear() {
113 stack.remove();
114 }
115
116 public int size() {
117 final List<String> result = stack.get();
118 return result == null ? 0 : result.size();
119 }
120
121 public boolean isEmpty() {
122 final List<String> result = stack.get();
123 return result == null || result.isEmpty();
124 }
125
126 public boolean contains(Object o) {
127 final List<String> result = stack.get();
128 return result != null && result.contains(o);
129 }
130
131 public Iterator<String> iterator() {
132 final List<String> immutable = stack.get();
133 if (immutable == null) {
134 final List<String> empty = Collections.emptyList();
135 return empty.iterator();
136 }
137 return immutable.iterator();
138 }
139
140 public Object[] toArray() {
141 final List<String> result = stack.get();
142 if (result == null) {
143 return new String[0];
144 }
145 return result.toArray(new Object[result.size()]);
146 }
147
148 public <T> T[] toArray(T[] ts) {
149 List<String> result = stack.get();
150 if (result == null) {
151 if (ts.length > 0) {
152 ts[0] = null;
153 }
154 return ts;
155 }
156 return result.toArray(ts);
157 }
158
159 public boolean add(String s) {
160 if (!useStack) {
161 return false;
162 }
163 final List<String> list = stack.get();
164 final List<String> copy = list == null ? new ArrayList<String>()
165 : new ArrayList<String>(list);
166 copy.add(s);
167 stack.set(Collections.unmodifiableList(copy));
168 return true;
169 }
170
171 public boolean remove(Object o) {
172 if (!useStack) {
173 return false;
174 }
175 final List<String> list = stack.get();
176 if (list == null || list.size() == 0) {
177 return false;
178 }
179 final List<String> copy = new ArrayList<String>(list);
180 final boolean result = copy.remove(o);
181 stack.set(Collections.unmodifiableList(copy));
182 return result;
183 }
184
185 public boolean containsAll(Collection<?> objects) {
186 if (objects.isEmpty()) {
187 return true;
188
189 }
190 final List<String> list = stack.get();
191 return list != null && list.containsAll(objects);
192 }
193
194 public boolean addAll(Collection<? extends String> strings) {
195 if (!useStack || strings.isEmpty()) {
196 return false;
197 }
198 final List<String> list = stack.get();
199 final List<String> copy = list == null ? new ArrayList<String>()
200 : new ArrayList<String>(list);
201 copy.addAll(strings);
202 stack.set(Collections.unmodifiableList(copy));
203 return true;
204 }
205
206 public boolean removeAll(Collection<?> objects) {
207 if (!useStack || objects.isEmpty()) {
208 return false;
209 }
210 final List<String> list = stack.get();
211 if (list == null || list.isEmpty()) {
212 return false;
213 }
214 final List<String> copy = new ArrayList<String>(list);
215 boolean result = copy.removeAll(objects);
216 stack.set(Collections.unmodifiableList(copy));
217 return result;
218 }
219
220 public boolean retainAll(Collection<?> objects) {
221 if (!useStack || objects.isEmpty()) {
222 return false;
223 }
224 final List<String> list = stack.get();
225 if (list == null || list.isEmpty()) {
226 return false;
227 }
228 final List<String> copy = new ArrayList<String>(list);
229 final boolean result = copy.retainAll(objects);
230 stack.set(Collections.unmodifiableList(copy));
231 return result;
232 }
233 }