1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.model.processor;
16  
17  import ch.qos.logback.core.Appender;
18  import ch.qos.logback.core.Context;
19  import ch.qos.logback.core.joran.JoranConstants;
20  import ch.qos.logback.core.model.AppenderRefModel;
21  import ch.qos.logback.core.model.Model;
22  import ch.qos.logback.core.spi.AppenderAttachable;
23  
24  import java.util.Map;
25  
26  import static ch.qos.logback.core.model.processor.AppenderDeclarationAnalyser.isAppenderDeclared;
27  
28  public class AppenderRefModelHandler extends ModelHandlerBase {
29      boolean inError = false;
30  
31      public AppenderRefModelHandler(Context context) {
32          super(context);
33      }
34  
35      static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext ic) {
36          return new AppenderRefModelHandler(context);
37      }
38  
39      @Override
40      protected Class<? extends AppenderRefModel> getSupportedModelClass() {
41          return AppenderRefModel.class;
42      }
43  
44      @Override
45      public void handle(ModelInterpretationContext interpContext, Model model) throws ModelHandlerException {
46  
47          Object o = interpContext.peekObject();
48  
49          if (!(o instanceof AppenderAttachable)) {
50              inError = true;
51              String errMsg = "Could not find an AppenderAttachable at the top of execution stack. Near "
52                      + model.idString();
53              addError(errMsg);
54              return;
55          }
56  
57          AppenderRefModel appenderRefModel = (AppenderRefModel) model;
58          AppenderAttachable<?> appenderAttachable = (AppenderAttachable<?>) o;
59  
60          attachReferencedAppenders(interpContext, appenderRefModel, appenderAttachable);
61  
62      }
63  
64      @SuppressWarnings({ "unchecked", "rawtypes" })
65      void attachReferencedAppenders(ModelInterpretationContext mic, AppenderRefModel appenderRefModel,
66              AppenderAttachable<?> appenderAttachable) {
67          // appender ref should not be subject to substitution
68          String appenderName = appenderRefModel.getRef();
69  
70          if(!isAppenderDeclared(mic, appenderName)) {
71              addWarn("Appender named [" + appenderName + "] could not be found. Skipping attachment to "+appenderAttachable+".");
72              return;
73          }
74  
75          Map<String, Appender> appenderBag = (Map<String, Appender>) mic.getObjectMap().get(JoranConstants.APPENDER_BAG);
76  
77          Appender appender = appenderBag.get(appenderName);
78          if (appender == null) {
79              addError("Failed to find appender named [" + appenderName + "]");
80          } else {
81              addInfo("Attaching appender named [" + appenderName + "] to " + appenderAttachable);
82              appenderAttachable.addAppender(appender);
83          }
84  
85      }
86  }