001/* 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2026, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v2.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic.spi; 015 016import java.util.concurrent.CopyOnWriteArrayList; 017 018import org.slf4j.Marker; 019 020import ch.qos.logback.classic.Level; 021import ch.qos.logback.classic.Logger; 022import ch.qos.logback.classic.turbo.TurboFilter; 023import ch.qos.logback.core.spi.FilterReply; 024 025/** 026 * Implementation of TurboFilterAttachable. 027 * 028 * @author Ceki Gülcü 029 */ 030final public class TurboFilterList extends CopyOnWriteArrayList<TurboFilter> { 031 032 private static final long serialVersionUID = 1L; 033 034 /** 035 * Loop through the filters in the chain. As soon as a filter decides on ACCEPT 036 * or DENY, then that value is returned. If all turbo filters return NEUTRAL, 037 * then NEUTRAL is returned. 038 */ 039 public FilterReply getTurboFilterChainDecision(final Marker marker, final Logger logger, final Level level, 040 final String format, final Object[] params, final Throwable t) { 041 042 final int size = size(); 043 // caller may have already performed this check, but we do it here as well to be sure 044 if (size == 0) { 045 return FilterReply.NEUTRAL; 046 } 047 048 if (size == 1) { 049 try { 050 TurboFilter tf = get(0); 051 return tf.decide(marker, logger, level, format, params, t); 052 } catch (IndexOutOfBoundsException iobe) { 053 // concurrent modification detected, fall through to the general case 054 return FilterReply.NEUTRAL; 055 } 056 } 057 058 059 for (TurboFilter tf : this) { 060 final FilterReply r = tf.decide(marker, logger, level, format, params, t); 061 if (r == FilterReply.DENY || r == FilterReply.ACCEPT) { 062 return r; 063 } 064 } 065 066 return FilterReply.NEUTRAL; 067 } 068 069 070 /** 071 * Loop through the filters in the chain. As soon as a filter decides on ACCEPT 072 * or DENY, then that value is returned. If all turbo filters return NEUTRAL, 073 * then NEUTRAL is returned. 074 * 075 * @param logger the logger requesting a decision 076 * @param slf4jEvent the SLF4J logging event 077 * @return the decision of the turbo filter chain 078 * @since 1.5.21 079 */ 080 public FilterReply getTurboFilterChainDecision(Logger logger, org.slf4j.event.LoggingEvent slf4jEvent) { 081 082 final int size = size(); 083 // caller may have already performed this check, but we do it here as well to be sure 084 if (size == 0) { 085 return FilterReply.NEUTRAL; 086 } 087 088 if (size == 1) { 089 try { 090 TurboFilter tf = get(0); 091 return tf.decide(logger, slf4jEvent); 092 } catch (IndexOutOfBoundsException iobe) { 093 // concurrent modification detected, fall through to the general case 094 return FilterReply.NEUTRAL; 095 } 096 } 097 098 099 for (TurboFilter tf : this) { 100 final FilterReply r = tf.decide(logger, slf4jEvent); 101 if (r == FilterReply.DENY || r == FilterReply.ACCEPT) { 102 return r; 103 } 104 } 105 106 return FilterReply.NEUTRAL; 107 } 108 109}