ch.qos.logback.core.BasicStatusManager Maven / Gradle / Ivy
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.core;
import java.util.ArrayList;
import java.util.List;
import ch.qos.logback.core.helpers.CyclicBuffer;
import ch.qos.logback.core.spi.LogbackLock;
import ch.qos.logback.core.status.OnConsoleStatusListener;
import ch.qos.logback.core.status.Status;
import ch.qos.logback.core.status.StatusListener;
import ch.qos.logback.core.status.StatusManager;
public class BasicStatusManager implements StatusManager {
public static final int MAX_HEADER_COUNT = 150;
public static final int TAIL_SIZE = 150;
int count = 0;
// protected access was requested in http://jira.qos.ch/browse/LBCORE-36
final protected List statusList = new ArrayList();
final protected CyclicBuffer tailBuffer = new CyclicBuffer(
TAIL_SIZE);
final protected LogbackLock statusListLock = new LogbackLock();
int level = Status.INFO;
// protected access was requested in http://jira.qos.ch/browse/LBCORE-36
final protected List statusListenerList = new ArrayList();
final protected LogbackLock statusListenerListLock = new LogbackLock();
// Note on synchronization
// This class contains two separate locks statusListLock and
// statusListenerListLock guarding respectively the statusList+tailBuffer and
// statusListenerList fields. The locks are used internally
// without cycles. They are exposed to derived classes which should be careful
// not to create deadlock cycles.
/**
* Add a new status object.
*
* @param newStatus
* the status message to add
*/
public void add(Status newStatus) {
// LBCORE-72: fire event before the count check
fireStatusAddEvent(newStatus);
count++;
if (newStatus.getLevel() > level) {
level = newStatus.getLevel();
}
synchronized (statusListLock) {
if (statusList.size() < MAX_HEADER_COUNT) {
statusList.add(newStatus);
} else {
tailBuffer.add(newStatus);
}
}
}
public List getCopyOfStatusList() {
synchronized (statusListLock) {
List tList = new ArrayList(statusList);
tList.addAll(tailBuffer.asList());
return tList;
}
}
private void fireStatusAddEvent(Status status) {
synchronized (statusListenerListLock) {
for (StatusListener sl : statusListenerList) {
sl.addStatusEvent(status);
}
}
}
public void clear() {
synchronized (statusListLock) {
count = 0;
statusList.clear();
tailBuffer.clear();
}
}
public int getLevel() {
return level;
}
public int getCount() {
return count;
}
/**
* This implementation does not allow duplicate installations of OnConsoleStatusListener
* @param listener
*/
public void add(StatusListener listener) {
synchronized (statusListenerListLock) {
if(listener instanceof OnConsoleStatusListener) {
boolean alreadyPresent = checkForPresence(statusListenerList, listener.getClass());
if(alreadyPresent)
return;
}
statusListenerList.add(listener);
}
}
private boolean checkForPresence(List statusListenerList, Class> aClass) {
for(StatusListener e: statusListenerList) {
if(e.getClass() == aClass)
return true;
}
return false;
}
public void remove(StatusListener listener) {
synchronized (statusListenerListLock) {
statusListenerList.remove(listener);
}
}
public List getCopyOfStatusListenerList() {
synchronized (statusListenerListLock) {
return new ArrayList(statusListenerList);
}
}
}