View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core;
15  
16  import java.util.ArrayList;
17  import java.util.List;
18  
19  import ch.qos.logback.core.helpers.CyclicBuffer;
20  import ch.qos.logback.core.status.Status;
21  import ch.qos.logback.core.status.StatusListener;
22  import ch.qos.logback.core.status.StatusManager;
23  
24  public class BasicStatusManager implements StatusManager {
25  
26    public static final int MAX_HEADER_COUNT = 150;
27    public static final int TAIL_SIZE = 150;
28  
29    int count = 0;
30  
31    // protected access was requested in http://jira.qos.ch/browse/LBCORE-36
32    final protected List<Status> statusList = new ArrayList<Status>();
33    final protected CyclicBuffer<Status> tailBuffer = new CyclicBuffer<Status>(
34        TAIL_SIZE);
35    final protected Object statusListLock = new Object();
36  
37    int level = Status.INFO;
38  
39    // protected access was requested in http://jira.qos.ch/browse/LBCORE-36
40    final protected List<StatusListener> statusListenerList = new ArrayList<StatusListener>();
41    final protected Object statusListenerListLock = new Object();
42  
43    // Note on synchronization
44    // This class contains two separate locks statusListLock and
45    // statusListenerListLock guarding respectively the statusList+tailBuffer and
46    // statusListenerList fields. The locks are used internally
47    // without cycles. They are exposed to derived classes which should be careful
48    // not to create deadlock cycles.
49  
50    /**
51     * Add a new status object.
52     * 
53     * @param Status
54     *                the status message to add
55     */
56    public void add(Status newStatus) {
57      // LBCORE-72: fire event before the count check
58      fireStatusAddEvent(newStatus);
59  
60      count++;
61      if (newStatus.getLevel() > level) {
62        level = newStatus.getLevel();
63      }
64  
65      synchronized (statusListLock) {
66        if (statusList.size() < MAX_HEADER_COUNT) {
67          statusList.add(newStatus);
68        } else {
69          tailBuffer.add(newStatus);
70        }
71      }
72  
73    }
74  
75    public List<Status> getCopyOfStatusList() {
76      synchronized (statusListLock) {
77        List<Status> tList = new ArrayList<Status>(statusList);
78        tList.addAll(tailBuffer.asList());
79        return tList;
80      }
81    }
82  
83    private void fireStatusAddEvent(Status status) {
84      synchronized (statusListenerListLock) {
85        for (StatusListener sl : statusListenerList) {
86          sl.addStatusEvent(status);
87        }
88      }
89    }
90  
91    public void clear() {
92      synchronized (statusListLock) {
93        count = 0;
94        statusList.clear();
95        tailBuffer.clear();
96      }
97    }
98  
99    public int getLevel() {
100     return level;
101   }
102 
103   public int getCount() {
104     return count;
105   }
106 
107   public void add(StatusListener listener) {
108     synchronized (statusListenerListLock) {
109       statusListenerList.add(listener);
110     }
111   }
112 
113   public void remove(StatusListener listener) {
114     synchronized (statusListenerListLock) {
115       statusListenerList.remove(listener);
116     }
117   }
118 
119   public List<StatusListener> getCopyOfStatusListenerList() {
120     synchronized (statusListenerListLock) {
121       return new ArrayList<StatusListener>(statusListenerList);
122     }
123   }
124 
125 }