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