/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.log4j.filter;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.OptionHandler;
import org.apache.log4j.xml.UnrecognizedElementHandler;
import org.w3c.dom.Element;
import java.util.Properties;
/**
* A filter that 'and's the results of any number of contained filters together.
*
* For the filter to process events, all contained filters must return Filter.ACCEPT.
*
* If the contained filters do not return Filter.ACCEPT, Filter.NEUTRAL is returned.
*
* If acceptOnMatch is set to true, Filter.ACCEPT is returned.
* If acceptOnMatch is set to false, Filter.DENY is returned.
*
* Here is an example config that will accept only events that contain BOTH
* a DEBUG level AND 'test' in the message:
*
*<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
* <filter class="org.apache.log4j.filter.AndFilter">
* <filter class="org.apache.log4j.filter.LevelMatchFilter">
* <param name="levelToMatch" value="DEBUG" />
* <param name="acceptOnMatch" value="true" />
* </filter>
* <filter class="org.apache.log4j.filter.StringMatchFilter">
* <param name="stringToMatch" value="test" />
* <param name="acceptOnMatch" value="true" />
* </filter>
* <param name="acceptOnMatch" value="false"/>
* </filter>
* <filter class="org.apache.log4j.filter.DenyAllFilter"/>
*<layout class="org.apache.log4j.SimpleLayout"/>
*</appender>
*
* To accept all events EXCEPT those events that contain a
* DEBUG level and 'test' in the message:
* change the AndFilter's acceptOnMatch param to false and remove the DenyAllFilter
*
* NOTE: If you are defining a filter that is only relying on logging event content
* (no external or filter-managed state), you could opt instead
* to use an ExpressionFilter with one of the following expressions:
*
* LEVEL == DEBUG && MSG ~= 'test'
* or
* ! ( LEVEL == DEBUG && MSG ~= 'test' )
*
* XML configuration of this filter requires use of either log4j 1.2.15 or later or
* org.apache.log4j.rolling.DOMConfigurator.
*
* @author Scott Deboy sdeboy@apache.org
*/
public class AndFilter extends Filter implements UnrecognizedElementHandler {
Filter headFilter = null;
Filter tailFilter = null;
boolean acceptOnMatch = true;
public void activateOptions() {
}
public void addFilter(final Filter filter) {
if (headFilter == null) {
headFilter = filter;
tailFilter = filter;
} else {
tailFilter.next = filter;
}
}
public void setAcceptOnMatch(final boolean acceptOnMatch) {
this.acceptOnMatch = acceptOnMatch;
}
/**
* If this event does not already contain location information,
* evaluate the event against the expression.
*
* If the expression evaluates to true, generate a LocationInfo instance
* by creating an exception and set this LocationInfo on the event.
*
* Returns {@link Filter#NEUTRAL}
*/
public int decide(final LoggingEvent event) {
boolean accepted = true;
Filter f = headFilter;
while (f != null) {
accepted = accepted && (Filter.ACCEPT == f.decide(event));
f = f.next;
}
if (accepted) {
if(acceptOnMatch) {
return Filter.ACCEPT;
}
return Filter.DENY;
}
return Filter.NEUTRAL;
}
/**
* {@inheritDoc}
*/
public boolean parseUnrecognizedElement(final Element element,
final Properties props) throws Exception {
final String nodeName = element.getNodeName();
if ("filter".equals(nodeName)) {
OptionHandler filter =
org.apache.log4j.extras.DOMConfigurator.parseElement(
element, props, Filter.class);
if (filter instanceof Filter) {
filter.activateOptions();
this.addFilter((Filter) filter);
}
return true;
}
return false;
}
}