001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2022, QOS.ch. All rights reserved. 004 * <p> 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * <p> 009 * or (per the licensee's choosing) 010 * <p> 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.core.joran.sanity; 015 016import ch.qos.logback.core.model.AppenderModel; 017import ch.qos.logback.core.model.Model; 018import ch.qos.logback.core.spi.ContextAwareBase; 019 020import java.util.ArrayList; 021import java.util.List; 022import java.util.stream.Collectors; 023 024public class AppenderWithinAppenderSanityChecker extends ContextAwareBase implements SanityChecker { 025 026 static public String NESTED_APPENDERS_WARNING = "As of logback version 1.3, nested appenders are not allowed."; 027 028 @Override 029 public void check(Model model) { 030 if (model == null) 031 return; 032 033 List<Model> appenderModels = new ArrayList<>(); 034 deepFindAllModelsOfType(AppenderModel.class, appenderModels, model); 035 036 List<Pair<Model, Model>> nestedPairs = deepFindNestedSubModelsOfType(AppenderModel.class, appenderModels); 037 038 List<Pair<Model, Model>> filteredNestedPairs = nestedPairs.stream().filter(pair -> !isSiftingAppender(pair.first)).collect(Collectors.toList()); 039 040 if(filteredNestedPairs.isEmpty()) { 041 return; 042 } 043 addWarn(NESTED_APPENDERS_WARNING); 044 for(Pair<Model, Model> pair: filteredNestedPairs) { 045 addWarn("Appender at line "+pair.first.getLineNumber() + " contains a nested appender at line "+pair.second.getLineNumber()); 046 } 047 } 048 049 private boolean isSiftingAppender(Model first) { 050 if(first instanceof AppenderModel) { 051 AppenderModel appenderModel = (AppenderModel) first; 052 String classname = appenderModel.getClassName(); 053 if(classname == null) 054 return false; 055 return appenderModel.getClassName().contains("SiftingAppender"); 056 } 057 return false; 058 } 059 060}