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.classic.model.processor;
16  
17  import ch.qos.logback.classic.joran.PropertiesConfigurator;
18  import ch.qos.logback.classic.model.ConfigurationModel;
19  import ch.qos.logback.classic.model.PropertiesConfiguratorModel;
20  import ch.qos.logback.core.Context;
21  import ch.qos.logback.core.joran.spi.JoranException;
22  import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
23  import ch.qos.logback.core.model.Model;
24  import ch.qos.logback.core.model.ResourceModel;
25  import ch.qos.logback.core.model.processor.ModelHandlerException;
26  import ch.qos.logback.core.model.processor.ModelInterpretationContext;
27  import ch.qos.logback.core.model.processor.ResourceHandlerBase;
28  import ch.qos.logback.core.spi.ContextAwarePropertyContainer;
29  import ch.qos.logback.core.util.OptionHelper;
30  
31  import java.io.InputStream;
32  import java.net.URL;
33  
34  public class PropertiesConfiguratorModelHandler extends ResourceHandlerBase {
35      boolean inError = false;
36  
37      static final boolean CREATE_CWL_IF_NOT_ALREADY_CREATED = true;
38  
39      public PropertiesConfiguratorModelHandler(Context context) {
40          super(context);
41      }
42  
43      static public PropertiesConfiguratorModelHandler makeInstance(Context context, ModelInterpretationContext mic) {
44          return new PropertiesConfiguratorModelHandler(context);
45      }
46  
47      @Override
48      public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
49  
50          Boolean topScanBoolean = mic.getTopScanBoolean();
51          detachedHandle(mic, model, topScanBoolean);
52      }
53  
54      /**
55       *
56       * Used by {@link #handle(ModelInterpretationContext, Model)} as well as logback-tyler. Note the widening of the
57       * base from {@link ModelInterpretationContext} to {@link ContextAwarePropertyContainer}.
58       *
59       * @param capc
60       * @param model
61       * @throws ModelHandlerException
62       * @since 1.5.10
63       */
64      public void detachedHandle(ContextAwarePropertyContainer capc, Model model, Boolean topScanBoolean) throws ModelHandlerException {
65  
66          PropertiesConfiguratorModel propertyConfiguratorModel = (PropertiesConfiguratorModel) model;
67  
68          this.optional = OptionHelper.toBoolean(propertyConfiguratorModel.getOptional(), false);
69  
70          if (!checkAttributes(propertyConfiguratorModel)) {
71              inError = true;
72              return;
73          }
74  
75          URL inputURL = getInputURL(capc, propertyConfiguratorModel);
76          if (inputURL == null) {
77              inError = true;
78              return;
79          }
80  
81  
82          Boolean localScan = OptionHelper.toBooleanObject(propertyConfiguratorModel.getScanStr());
83  
84          InputStream in = openURL(inputURL);
85          if (in == null) {
86              inError = true;
87              return;
88          }
89  
90          if(localScan == Boolean.TRUE || topScanBoolean == Boolean.TRUE) {
91              if(topScanBoolean != Boolean.TRUE) {
92                  // if topScanBoolean ia not TRUE, then a ConfigurationWatchList has not been created and registered, yet
93                  // we need to do so now
94                  ConfigurationWatchListUtil.registerNewConfigurationWatchListWithContext(context);
95              }
96              ConfigurationWatchListUtil.addToWatchList(context, inputURL, CREATE_CWL_IF_NOT_ALREADY_CREATED);
97          }
98  
99  
100 
101         addInfo("Reading configuration from [" + getAttribureInUse() + "]");
102 
103         PropertiesConfigurator propertiesConfigurator = new PropertiesConfigurator();
104         propertiesConfigurator.setContext(capc.getContext());
105         try {
106             propertiesConfigurator.doConfigure(in);
107         } catch (JoranException e) {
108             addError("Could not configure from " + getAttribureInUse());
109             throw new ModelHandlerException(e);
110         }
111 
112     }
113 
114     protected InputStream getInputStream(ContextAwarePropertyContainer capc, ResourceModel resourceModel) {
115         URL inputURL = getInputURL(capc, resourceModel);
116         if (inputURL == null)
117             return null;
118 
119 
120 
121         ConfigurationWatchListUtil.addToWatchList(context, inputURL, CREATE_CWL_IF_NOT_ALREADY_CREATED);
122         return openURL(inputURL);
123     }
124 
125 }