001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements. See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache license, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License. You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the license for the specific language governing permissions and
015     * limitations under the license.
016     */
017    package org.apache.logging.log4j.spi;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Iterator;
022    import java.util.List;
023    
024    /**
025     *
026     */
027    public class MutableThreadContextStack implements ThreadContextStack {
028    
029        private static final long serialVersionUID = 50505011L;
030    
031        /**
032         * The underlying list (never null).
033         */
034        private final List<String> list;
035    
036        public MutableThreadContextStack(final List<String> list) {
037            this.list = new ArrayList<String>(list);
038        }
039    
040        private MutableThreadContextStack(final MutableThreadContextStack stack) {
041            this.list = new ArrayList<String>(stack.list);
042        }
043    
044        @Override
045        public String pop() {
046            if (list.isEmpty()) {
047                return null;
048            }
049            final int last = list.size() - 1;
050            final String result = list.remove(last);
051            return result;
052        }
053    
054        @Override
055        public String peek() {
056            if (list.isEmpty()) {
057                return null;
058            }
059            final int last = list.size() - 1;
060            return list.get(last);
061        }
062    
063        @Override
064        public void push(final String message) {
065            list.add(message);
066        }
067    
068        @Override
069        public int getDepth() {
070            return list.size();
071        }
072    
073        @Override
074        public List<String> asList() {
075            return list;
076        }
077    
078        @Override
079        public void trim(final int depth) {
080            if (depth < 0) {
081                throw new IllegalArgumentException("Maximum stack depth cannot be negative");
082            }
083            if (list == null) {
084                return;
085            }
086            final List<String> copy = new ArrayList<String>(list.size());
087            final int count = Math.min(depth, list.size());
088            for (int i = 0; i < count; i++) {
089                copy.add(list.get(i));
090            }
091            list.clear();
092            list.addAll(copy);
093        }
094    
095        @Override
096        public ThreadContextStack copy() {
097            return new MutableThreadContextStack(this);
098        }
099    
100        @Override
101        public void clear() {
102            list.clear();
103        }
104    
105        @Override
106        public int size() {
107            return list.size();
108        }
109    
110        @Override
111        public boolean isEmpty() {
112            return list.isEmpty();
113        }
114    
115        @Override
116        public boolean contains(final Object o) {
117            return list.contains(o);
118        }
119    
120        @Override
121        public Iterator<String> iterator() {
122            return list.iterator();
123        }
124    
125        @Override
126        public Object[] toArray() {
127            return list.toArray();
128        }
129    
130        @Override
131        public <T> T[] toArray(final T[] ts) {
132            return list.toArray(ts);
133        }
134    
135        @Override
136        public boolean add(final String s) {
137            return list.add(s);
138        }
139    
140        @Override
141        public boolean remove(final Object o) {
142            return list.remove(o);
143        }
144    
145        @Override
146        public boolean containsAll(final Collection<?> objects) {
147            return list.containsAll(objects);
148        }
149    
150        @Override
151        public boolean addAll(final Collection<? extends String> strings) {
152            return list.addAll(strings);
153        }
154    
155        @Override
156        public boolean removeAll(final Collection<?> objects) {
157            return list.removeAll(objects);
158        }
159    
160        @Override
161        public boolean retainAll(final Collection<?> objects) {
162            return list.retainAll(objects);
163        }
164    
165        @Override
166        public String toString() {
167            return String.valueOf(list);
168        }
169    
170        @Override
171        public int hashCode() {
172            final int prime = 31;
173            int result = 1;
174            result = prime * result + ((this.list == null) ? 0 : this.list.hashCode());
175            return result;
176        }
177    
178        @Override
179        public boolean equals(Object obj) {
180            if (this == obj) {
181                return true;
182            }
183            if (obj == null) {
184                return false;
185            }
186            if (!(obj instanceof ThreadContextStack)) {
187                return false;
188            }
189            ThreadContextStack other = (ThreadContextStack) obj;
190            final List<String> otherAsList = other.asList();
191            if (this.list == null) {
192                if (otherAsList != null) {
193                    return false;
194                }
195            } else if (!this.list.equals(otherAsList)) {
196                return false;
197            }
198            return true;
199        }
200    }