View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
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       * The underlying list (never null).
35       */
36      private final List<String> list;
37      private boolean frozen;
38  
39      /**
40       * Constructs an empty MutableThreadContextStack.
41       */
42      public MutableThreadContextStack() {
43          this(new ArrayList<String>());
44      }
45  
46      public MutableThreadContextStack(final List<String> list) {
47          this.list = new ArrayList<String>(list);
48      }
49  
50      private MutableThreadContextStack(final MutableThreadContextStack stack) {
51          this.list = new ArrayList<String>(stack.list);
52      }
53  
54      private void checkInvariants() {
55          if (frozen) {
56              throw new UnsupportedOperationException("context stack has been frozen");
57          }
58      }
59  
60      @Override
61      public String pop() {
62          checkInvariants();
63          if (list.isEmpty()) {
64              return null;
65          }
66          final int last = list.size() - 1;
67          final String result = list.remove(last);
68          return result;
69      }
70  
71      @Override
72      public String peek() {
73          if (list.isEmpty()) {
74              return null;
75          }
76          final int last = list.size() - 1;
77          return list.get(last);
78      }
79  
80      @Override
81      public void push(final String message) {
82          checkInvariants();
83          list.add(message);
84      }
85  
86      @Override
87      public int getDepth() {
88          return list.size();
89      }
90  
91      @Override
92      public List<String> asList() {
93          return list;
94      }
95  
96      @Override
97      public void trim(final int depth) {
98          checkInvariants();
99          if (depth < 0) {
100             throw new IllegalArgumentException("Maximum stack depth cannot be negative");
101         }
102         if (list == null) {
103             return;
104         }
105         final List<String> copy = new ArrayList<String>(list.size());
106         final int count = Math.min(depth, list.size());
107         for (int i = 0; i < count; i++) {
108             copy.add(list.get(i));
109         }
110         list.clear();
111         list.addAll(copy);
112     }
113 
114     @Override
115     public ThreadContextStack copy() {
116         return new MutableThreadContextStack(this);
117     }
118 
119     @Override
120     public void clear() {
121         checkInvariants();
122         list.clear();
123     }
124 
125     @Override
126     public int size() {
127         return list.size();
128     }
129 
130     @Override
131     public boolean isEmpty() {
132         return list.isEmpty();
133     }
134 
135     @Override
136     public boolean contains(final Object o) {
137         return list.contains(o);
138     }
139 
140     @Override
141     public Iterator<String> iterator() {
142         return list.iterator();
143     }
144 
145     @Override
146     public Object[] toArray() {
147         return list.toArray();
148     }
149 
150     @Override
151     public <T> T[] toArray(final T[] ts) {
152         return list.toArray(ts);
153     }
154 
155     @Override
156     public boolean add(final String s) {
157         checkInvariants();
158         return list.add(s);
159     }
160 
161     @Override
162     public boolean remove(final Object o) {
163         checkInvariants();
164         return list.remove(o);
165     }
166 
167     @Override
168     public boolean containsAll(final Collection<?> objects) {
169         return list.containsAll(objects);
170     }
171 
172     @Override
173     public boolean addAll(final Collection<? extends String> strings) {
174         checkInvariants();
175         return list.addAll(strings);
176     }
177 
178     @Override
179     public boolean removeAll(final Collection<?> objects) {
180         checkInvariants();
181         return list.removeAll(objects);
182     }
183 
184     @Override
185     public boolean retainAll(final Collection<?> objects) {
186         checkInvariants();
187         return list.retainAll(objects);
188     }
189 
190     @Override
191     public String toString() {
192         return String.valueOf(list);
193     }
194 
195     @Override
196     public int hashCode() {
197         final int prime = 31;
198         int result = 1;
199         result = prime * result + ((this.list == null) ? 0 : this.list.hashCode());
200         return result;
201     }
202 
203     @Override
204     public boolean equals(final Object obj) {
205         if (this == obj) {
206             return true;
207         }
208         if (obj == null) {
209             return false;
210         }
211         if (!(obj instanceof ThreadContextStack)) {
212             return false;
213         }
214         final ThreadContextStack other = (ThreadContextStack) obj;
215         final List<String> otherAsList = other.asList();
216         if (this.list == null) {
217             if (otherAsList != null) {
218                 return false;
219             }
220         } else if (!this.list.equals(otherAsList)) {
221             return false;
222         }
223         return true;
224     }
225 
226     @Override
227     public ContextStack getImmutableStackOrNull() {
228         return copy();
229     }
230 
231     /**
232      * "Freezes" this context stack so it becomes immutable: all mutator methods will throw an exception from now on.
233      */
234     public void freeze() {
235         frozen = true;
236     }
237     
238     public boolean isFrozen() {
239         return frozen;
240     }
241 }