View Javadoc

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