001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.filter; 018 019import java.util.Iterator; 020import java.util.concurrent.TimeUnit; 021 022import org.apache.logging.log4j.core.AbstractLifeCycle; 023import org.apache.logging.log4j.core.Filter; 024import org.apache.logging.log4j.core.LifeCycle2; 025import org.apache.logging.log4j.core.LogEvent; 026import org.apache.logging.log4j.core.config.plugins.PluginElement; 027 028/** 029 * Enhances a Class by allowing it to contain Filters. 030 */ 031public abstract class AbstractFilterable extends AbstractLifeCycle implements Filterable { 032 033 /** 034 * Subclasses can extend this abstract Builder. 035 * 036 * @param <B> The type to build. 037 */ 038 public abstract static class Builder<B extends Builder<B>> { 039 040 @PluginElement("Filter") 041 private Filter filter; 042 043 public Filter getFilter() { 044 return filter; 045 } 046 047 @SuppressWarnings("unchecked") 048 public B asBuilder() { 049 return (B) this; 050 } 051 052 public B withFilter(final Filter filter) { 053 this.filter = filter; 054 return asBuilder(); 055 } 056 057 } 058 059 /** 060 * May be null. 061 */ 062 private volatile Filter filter; 063 064 protected AbstractFilterable(final Filter filter) { 065 this.filter = filter; 066 } 067 068 protected AbstractFilterable() { 069 } 070 071 /** 072 * Returns the Filter. 073 * @return the Filter or null. 074 */ 075 @Override 076 public Filter getFilter() { 077 return filter; 078 } 079 080 /** 081 * Adds a filter. 082 * @param filter The Filter to add. 083 */ 084 @Override 085 public synchronized void addFilter(final Filter filter) { 086 if (filter == null) { 087 return; 088 } 089 if (this.filter == null) { 090 this.filter = filter; 091 } else if (this.filter instanceof CompositeFilter) { 092 this.filter = ((CompositeFilter) this.filter).addFilter(filter); 093 } else { 094 final Filter[] filters = new Filter[] {this.filter, filter}; 095 this.filter = CompositeFilter.createFilters(filters); 096 } 097 } 098 099 /** 100 * Removes a Filter. 101 * @param filter The Filter to remove. 102 */ 103 @Override 104 public synchronized void removeFilter(final Filter filter) { 105 if (this.filter == null || filter == null) { 106 return; 107 } 108 if (this.filter == filter || this.filter.equals(filter)) { 109 this.filter = null; 110 } else if (this.filter instanceof CompositeFilter) { 111 CompositeFilter composite = (CompositeFilter) this.filter; 112 composite = composite.removeFilter(filter); 113 if (composite.size() > 1) { 114 this.filter = composite; 115 } else if (composite.size() == 1) { 116 final Iterator<Filter> iter = composite.iterator(); 117 this.filter = iter.next(); 118 } else { 119 this.filter = null; 120 } 121 } 122 } 123 124 /** 125 * Determines if a Filter is present. 126 * @return false if no Filter is present. 127 */ 128 @Override 129 public boolean hasFilter() { 130 return filter != null; 131 } 132 133 /** 134 * Make the Filter available for use. 135 */ 136 @Override 137 public void start() { 138 this.setStarting(); 139 if (filter != null) { 140 filter.start(); 141 } 142 this.setStarted(); 143 } 144 145 /** 146 * Cleanup the Filter. 147 */ 148 @Override 149 public boolean stop(final long timeout, final TimeUnit timeUnit) { 150 return stop(timeout, timeUnit, true); 151 } 152 153 /** 154 * Cleanup the Filter. 155 */ 156 protected boolean stop(final long timeout, final TimeUnit timeUnit, final boolean changeLifeCycleState) { 157 if (changeLifeCycleState) { 158 this.setStopping(); 159 } 160 boolean stopped = true; 161 if (filter != null) { 162 if (filter instanceof LifeCycle2) { 163 stopped = ((LifeCycle2) filter).stop(timeout, timeUnit); 164 } else { 165 filter.stop(); 166 stopped = true; 167 } 168 } 169 if (changeLifeCycleState) { 170 this.setStopped(); 171 } 172 return stopped; 173 } 174 175 /** 176 * Determine if the LogEvent should be processed or ignored. 177 * @param event The LogEvent. 178 * @return true if the LogEvent should be processed. 179 */ 180 @Override 181 public boolean isFiltered(final LogEvent event) { 182 return filter != null && filter.filter(event) == Filter.Result.DENY; 183 } 184 185}