1
2
3
4
5
6
7
8
9
10
11 package ch.qos.logback.classic.util;
12
13 import ch.qos.logback.classic.ClassicConstants;
14 import ch.qos.logback.classic.LoggerContext;
15 import ch.qos.logback.classic.spi.Configurator;
16 import ch.qos.logback.classic.spi.ConfiguratorRank;
17 import ch.qos.logback.core.CoreConstants;
18 import ch.qos.logback.core.LogbackException;
19 import ch.qos.logback.core.joran.spi.JoranException;
20 import ch.qos.logback.core.spi.ContextAware;
21 import ch.qos.logback.core.spi.ContextAwareImpl;
22 import ch.qos.logback.core.status.InfoStatus;
23 import ch.qos.logback.core.status.WarnStatus;
24 import ch.qos.logback.core.util.EnvUtil;
25 import ch.qos.logback.core.util.Loader;
26 import ch.qos.logback.core.util.StatusListenerConfigHelper;
27
28 import java.util.Comparator;
29 import java.util.List;
30
31
32
33
34
35
36
37
38
39 public class ContextInitializer {
40
41
42
43
44 final public static String AUTOCONFIG_FILE = ClassicConstants.AUTOCONFIG_FILE;
45
46
47
48 final public static String TEST_AUTOCONFIG_FILE = ClassicConstants.TEST_AUTOCONFIG_FILE;
49
50
51
52 final public static String CONFIG_FILE_PROPERTY = ClassicConstants.CONFIG_FILE_PROPERTY;
53
54 String[] INTERNAL_CONFIGURATOR_CLASSNAME_LIST = {"ch.qos.logback.classic.joran.SerializedModelConfigurator",
55 "ch.qos.logback.classic.util.DefaultJoranConfigurator", "ch.qos.logback.classic.BasicConfigurator"};
56
57 final LoggerContext loggerContext;
58
59 final ContextAware contextAware;
60
61 public ContextInitializer(LoggerContext loggerContext) {
62 this.loggerContext = loggerContext;
63 this.contextAware = new ContextAwareImpl(loggerContext, this);
64 }
65
66 public void autoConfig() throws JoranException {
67 autoConfig(Configurator.class.getClassLoader());
68 }
69
70
71 public void autoConfig(ClassLoader classLoader) throws JoranException {
72
73
74 classLoader = Loader.systemClassloaderIfNull(classLoader);
75
76 checkVersions();
77
78 StatusListenerConfigHelper.installIfAsked(loggerContext);
79
80
81
82 List<Configurator> configuratorList = ClassicEnvUtil.loadFromServiceLoader(Configurator.class, classLoader);
83 configuratorList.sort(rankComparator);
84 if (configuratorList.isEmpty()) {
85 contextAware.addInfo("No custom configurators were discovered as a service.");
86 } else {
87 printConfiguratorOrder(configuratorList);
88 }
89
90 for (Configurator c : configuratorList) {
91 if (invokeConfigure(c) == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY)
92 return;
93 }
94
95
96 for (String configuratorClassName : INTERNAL_CONFIGURATOR_CLASSNAME_LIST) {
97 contextAware.addInfo("Trying to configure with "+configuratorClassName);
98 Configurator c = instantiateConfiguratorByClassName(configuratorClassName, classLoader);
99 if(c == null)
100 continue;
101 if (invokeConfigure(c) == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY)
102 return;
103 }
104 }
105
106 private void checkVersions() {
107 String versionOfLogbackClassic = ClassicEnvUtil.getVersionOfLogbackClassic();
108 if (versionOfLogbackClassic == null) {
109 versionOfLogbackClassic = CoreConstants.NA;
110 }
111 String versionOfLogbackCore = EnvUtil.logbackVersion();
112 if (versionOfLogbackCore == null) {
113 versionOfLogbackCore = CoreConstants.NA;
114 }
115 loggerContext.getStatusManager().add(new InfoStatus(ClassicConstants.LOGBACK_CLASSIC_VERSION_MESSAGE + versionOfLogbackClassic, loggerContext));
116 if(!versionOfLogbackCore.equals(versionOfLogbackClassic)) {
117 loggerContext.getStatusManager().add(new InfoStatus(CoreConstants.LOGBACK_CORE_VERSION_MESSAGE + versionOfLogbackCore, loggerContext));
118 loggerContext.getStatusManager().add(new WarnStatus(ClassicConstants.LOGBACK_VERSIONS_MISMATCH, loggerContext));
119 }
120 }
121
122 private Configurator instantiateConfiguratorByClassName(String configuratorClassName, ClassLoader classLoader) {
123 try {
124 Class<?> classObj = classLoader.loadClass(configuratorClassName);
125 return (Configurator) classObj.getConstructor().newInstance();
126 } catch (ReflectiveOperationException e) {
127 contextAware.addInfo("Instantiation failure: " + e.toString());
128 return null;
129 }
130 }
131
132
133
134
135
136
137 private Configurator.ExecutionStatus invokeConfigure(Configurator configurator) {
138 try {
139 long start = System.currentTimeMillis();
140 contextAware.addInfo("Constructed configurator of type " + configurator.getClass());
141 configurator.setContext(loggerContext);
142 Configurator.ExecutionStatus status = configurator.configure(loggerContext);
143 printDuration(start, configurator, status);
144 return status;
145
146 } catch (Exception e) {
147 throw new LogbackException(String.format("Failed to initialize or to run Configurator: %s",
148 configurator != null ? configurator.getClass().getCanonicalName() : "null"), e);
149 }
150 }
151
152 private void printConfiguratorOrder(List<Configurator> configuratorList) {
153 contextAware.addInfo("Here is a list of configurators discovered as a service, by rank: ");
154 for(Configurator c: configuratorList) {
155 contextAware.addInfo(" "+c.getClass().getName());
156 }
157 contextAware.addInfo("They will be invoked in order until ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY is returned.");
158 }
159
160 private void printDuration(long start, Configurator configurator, Configurator.ExecutionStatus executionStatus) {
161 long end = System.currentTimeMillis();
162 long diff = end - start;
163 contextAware.addInfo( configurator.getClass().getName()+".configure() call lasted "+diff + " milliseconds. ExecutionStatus="+executionStatus);
164 }
165
166 private Configurator.ExecutionStatus attemptConfigurationUsingJoranUsingReflexion(ClassLoader classLoader) {
167
168 try {
169 Class<?> djcClass = classLoader.loadClass("ch.qos.logback.classic.util.DefaultJoranConfigurator");
170 Configurator c = (Configurator) djcClass.newInstance();
171 c.setContext(loggerContext);
172 return c.configure(loggerContext);
173 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
174 contextAware.addError("unexpected exception while instantiating DefaultJoranConfigurator", e);
175 return Configurator.ExecutionStatus.INVOKE_NEXT_IF_ANY;
176 }
177
178 }
179
180 Comparator<Configurator> rankComparator = new Comparator<Configurator>() {
181 @Override
182 public int compare(Configurator c1, Configurator c2) {
183
184 ConfiguratorRank r1 = c1.getClass().getAnnotation(ConfiguratorRank.class);
185 ConfiguratorRank r2 = c2.getClass().getAnnotation(ConfiguratorRank.class);
186
187 int value1 = r1 == null ? ConfiguratorRank.DEFAULT : r1.value();
188 int value2 = r2 == null ? ConfiguratorRank.DEFAULT : r2.value();
189
190 int result = compareRankValue(value1, value2);
191
192 return (-result);
193 }
194 };
195
196 private int compareRankValue(int value1, int value2) {
197 if(value1 > value2)
198 return 1;
199 else if (value1 == value2)
200 return 0;
201 else return -1;
202
203 }
204 }