/
JrdsLoggerConfiguration.java
192 lines (171 loc) · 6.97 KB
/
JrdsLoggerConfiguration.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package jrds;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Hierarchy;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
/**
* This class is used to setup the log environment.
* <p>
* The normal starting point for logger configuration is initLog4J(). But
* putAppender() can be used instead if log4j is already configured. It that's
* the case, the following steps must be done:
* <ul>
* <li>Define the jrds appender using putAppender.
* <li>Set additivity to false for the rootLoggers if this appender is used at
* an higher level.
* <li>Do not define a log file in the property file or PropertiesManager
* object.
* </ul>
*
* @author Fabrice Bacchella
*/
public class JrdsLoggerConfiguration {
static public final String APPENDERNAME = "jrdsAppender";
static public final String DEFAULTLOGFILE = "System.err";
static public final String DEFAULTLAYOUT = "[%d] %5p %c : %m%n";
static public Appender jrdsAppender = null;
// The managed loggers list
static public final Set<String> rootLoggers = new HashSet<String>(Arrays.asList(new String[]{"jrds", "org.mortbay.log", "org.apache", "org.eclipse.jetty"}));
// Used to check if jrds "own" the log configuration
// null = we don't know yet
static private Boolean logOwner = null;
/**
* The actual implementation of the logger helper methods is provided by this inner class.
* This is done in order to avoid {@link ClassNotFoundException} being thrown in the event
* log4j 2 API bridge is used by a calling application instead of the log4j 1.2 implementation.
* This works because the inner class is loaded lazily and only if {@link JrdsLoggerConfiguration#logOwner}
* is set to true {@code false}.
*/
private static class JrdsLoggerConfigurationWorker {
private static void initLog4J() throws IOException {
if (jrdsAppender == null) {
jrdsAppender = new ConsoleAppender(new org.apache.log4j.SimpleLayout(), DEFAULTLOGFILE);
jrdsAppender.setName(APPENDERNAME);
}
// Configure all the manager logger
// Default level is debug, not a very good idea
for (String loggerName : rootLoggers) {
configureLogger(loggerName, Level.ERROR);
}
}
private static void configure(PropertiesManager pm) throws IOException {
if (pm.logfile != null && !"".equals(pm.logfile)) {
jrdsAppender = new DailyRollingFileAppender(new PatternLayout(DEFAULTLAYOUT), pm.logfile, "'.'yyyy-ww");
jrdsAppender.setName(APPENDERNAME);
}
for (String logger : rootLoggers) {
configureLogger(logger, pm.loglevel);
}
// getLogger change the level of new loggers only
Logger.getLogger("jrds").setLevel(pm.loglevel);
for (Map.Entry<Level, List<String>> e : pm.loglevels.entrySet()) {
Level l = e.getKey();
for (String logName : e.getValue()) {
Logger.getLogger(logName).setLevel(l);
}
}
}
private static void configureLogger(String logname, Level level) {
Logger externallogger = LogManager.getLoggerRepository().exists(logname);
// Change level only for new logger
if (externallogger == null) {
externallogger = Logger.getLogger(logname);
externallogger.setLevel(level);
}
// Replace the appender, not optionally add it
if (jrdsAppender != null) {
Logger logger = Logger.getLogger(logname);
Appender oldApp = logger.getAppender(jrdsAppender.getName());
if (oldApp != null)
logger.removeAppender(oldApp);
logger.addAppender(jrdsAppender);
logger.setAdditivity(false);
}
// Keep the new logger name
rootLoggers.add(logname);
}
private static void reset() {
LogManager.resetConfiguration();
Hierarchy logHierarchy = (Hierarchy) LogManager.getLoggerRepository();
logHierarchy.clear();
logOwner = null;
jrdsAppender = null;
}
}
private JrdsLoggerConfiguration() {
}
/**
* Force an external log4j configuration, must be called before initLog4j
*/
static public void setExternal() {
logOwner = false;
}
static public void reset() {
if (isLogOwner()) {
JrdsLoggerConfigurationWorker.reset();
}
}
/**
* The method used to prepare a minimal set of logging configuration. This
* should be used once. It does nothing if it detect that a appender already
* exist for the logger <code>jrds</code>. The default logger is the system
* error output and the default level is error.
*
* @throws IOException
*/
static public void initLog4J() throws IOException {
// Do nothing if jrds is not allowed to setup logs
if (isLogOwner()) {
JrdsLoggerConfigurationWorker.initLog4J();
}
}
/**
* This method prepare the log4j environment using the configuration in
* jrds.properties. it uses the following properties
* <ul>
* <li><code>logfile</code>, used to define the log file, if not defined, no
* appender is created</li>
* <li><code>loglevel</code>, used to define the default loglevel</li>
* <li><code>log.<level></code>, followed by a comma separated list of
* logger, to set the level of those logger to <code>level</code></li>
* </ul>
*
* @param pm a configured PropertiesManager object
* @throws IOException
*/
static public void configure(PropertiesManager pm) throws IOException {
if (isLogOwner()) {
JrdsLoggerConfigurationWorker.configure(pm);
}
}
/**
* This method is used to join other logger branch with the jrds' one and
* use same setting if it's not already defined
*
* @param logname the logger name
* @param level the desired default level for this logger
*/
static public void configureLogger(String logname, Level level) {
if (isLogOwner()) {
JrdsLoggerConfigurationWorker.configureLogger(logname, level);
}
}
static private synchronized boolean isLogOwner() {
// logOwner == null mean we don't know yet
// if will be set to false if a logger called jrds already exist
if (logOwner == null) {
logOwner = LogManager.getLoggerRepository().exists("jrds") == null;
}
return logOwner;
}
}