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  package ch.qos.logback.core.joran.util;
15  
16  import ch.qos.logback.core.Context;
17  import ch.qos.logback.core.CoreConstants;
18  import ch.qos.logback.core.joran.spi.ConfigurationWatchList;
19  import ch.qos.logback.core.status.ErrorStatus;
20  import ch.qos.logback.core.status.InfoStatus;
21  import ch.qos.logback.core.status.Status;
22  import ch.qos.logback.core.status.StatusManager;
23  import ch.qos.logback.core.status.WarnStatus;
24  
25  import java.net.URL;
26  
27  /**
28   * A thin layer on top of {@link ConfigurationWatchList}.
29   *
30   * @author Ceki Gülcü
31   */
32  public class ConfigurationWatchListUtil {
33  
34      final static ConfigurationWatchListUtil ORIGIN = new ConfigurationWatchListUtil();
35  
36      private ConfigurationWatchListUtil() {
37      }
38  
39      public static void registerConfigurationWatchList(Context context, ConfigurationWatchList cwl) {
40          context.putObject(CoreConstants.CONFIGURATION_WATCH_LIST, cwl);
41      }
42  
43      /**
44       * Sets the main configuration watch URL in the given context's configuration watch list.
45       * If the provided URL is null, the method exits without making any changes.
46       * If the configuration watch list is not initialized, an error is added to the context's status.
47       * Otherwise, the configuration watch list is cleared and the given URL is set as the main URL.
48       *
49       * @param context the context in which the configuration watch list is managed
50       * @param url the main configuration watch URL to be set; if null, no action is taken
51       */
52      public static void setMainWatchURL(Context context, URL url) {
53          if(url == null) {
54              return;
55          }
56          ConfigurationWatchList cwl = getConfigurationWatchList(context);
57          if (cwl == null) {
58              addError(context, "ConfigurationWatchList should have been initialized at this stage.");
59              return;
60          } else {
61              cwl.clear();
62          }
63          cwl.setTopURL(url);
64      }
65  
66      /**
67       * Returns true if there are watchable files, false otherwise.
68       * @return true if there are watchable files,  false otherwise.
69       * @since 1.5.8
70       */
71      public static boolean watchPredicateFulfilled(Context context) {
72          ConfigurationWatchList cwl = getConfigurationWatchList(context);
73          if (cwl == null) {
74              return false;
75          }
76          return cwl.watchPredicateFulfilled();
77      }
78  
79      public static URL getMainWatchURL(Context context) {
80          ConfigurationWatchList cwl = getConfigurationWatchList(context);
81          if (cwl == null) {
82              return null;
83          } else {
84              return cwl.getTopURL();
85          }
86      }
87  
88      public static void addToWatchList(Context context, URL url) {
89          addToWatchList(context, url, false);
90      }
91  
92      public static void addToWatchList(Context context, URL url, boolean createCWL) {
93          ConfigurationWatchList cwl = getConfigurationWatchList(context);
94          if(cwl == null) {
95              if(createCWL && ConfigurationWatchList.isWatchableProtocol(url)) {
96                  cwl = registerNewConfigurationWatchListWithContext(context);
97              } else {
98                  addInfo(context, "ConfigurationWatchList not initialized due to absence of scan directive. Will not add " + url);
99                  return;
100             }
101         }
102 
103         String protocol = url.getProtocol();
104         if(cwl.isWatchableProtocol(protocol)) {
105             addInfo(context, "Will add [" + url + "] to configuration watch list.");
106             cwl.addToWatchList(url);
107         } else {
108             addInfo(context, "Will not add configuration file ["+url + "] to watch list, because '"+protocol+"' protocol is not watchable.");
109             addInfo(context, "Only the protocols 'file', 'http' and 'https' are watchable.");
110         }
111     }
112 
113     public static ConfigurationWatchList registerNewConfigurationWatchListWithContext(Context context) {
114         ConfigurationWatchList cwl = new ConfigurationWatchList();
115         cwl.setContext(context);
116         context.putObject(CoreConstants.CONFIGURATION_WATCH_LIST, cwl);
117         return cwl;
118     }
119 
120     public static ConfigurationWatchList getConfigurationWatchList(Context context) {
121         return (ConfigurationWatchList) context.getObject(CoreConstants.CONFIGURATION_WATCH_LIST);
122     }
123 
124     static void addStatus(Context context, Status s) {
125         if (context == null) {
126             System.out.println("Null context in " + ConfigurationWatchList.class.getName());
127             return;
128         }
129         StatusManager sm = context.getStatusManager();
130         if (sm == null)
131             return;
132         sm.add(s);
133     }
134 
135     static void addInfo(Context context, String msg) {
136        addStatus(context, new InfoStatus(msg, ORIGIN));
137     }
138 
139     static void addWarn(Context context, String msg) {
140         addStatus(context, new WarnStatus(msg, ORIGIN));
141     }
142     static void addError(Context context, String msg) {
143         addStatus(context, new ErrorStatus(msg, ORIGIN));
144     }
145 }