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 }