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