1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.webapp.logging;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.impl.Log4JLogger;
25 import org.apache.log4j.Hierarchy;
26
27 /***
28 * IsolatedLog4JLogger routes all commons-logging logging using Log4J to an ContextClassLoader
29 * specific Hierarchy.
30 * </p>
31 * <p>
32 * For web or application servers providing (and enforcing) commons-logging and
33 * Log4J from a shared context (like JBoss), configuring Log4J loggers and appenders
34 * from within a (web) application overrides and resets the global
35 * Log4J LoggerRepository.
36 * </p>
37 * <p>
38 * Capturing root logging for logging events from within the web application
39 * for example isn't possible using a Log4J propery or xml configuration without
40 * routing <em>ALL</em> root logging through the new (web application specific)
41 * configuration.
42 * </p>
43 * <p>
44 * <em>It is possible using the Log4J API directly instead of configuration files,
45 * but that requires hardcoded knowledge about how the logging is to be done.</em>
46 * </p>
47 * <p>
48 * Furthermore, if another application later on reconfigures the root logging again, the
49 * current root logging configuration is closed, detached and rerouted to the new configuration.
50 * </p>
51 * <p>
52 * The same applies of course to common named loggers like capturing springframework logging.
53 * </p>
54 * <p>
55 * The only way to prevent this <em>stealing</em> of logging configuration is allowing only
56 * one log4J configuration for the whole web or application server.<br/>
57 * As this has to be done in a web or application server specific manner, setting up Jetspeed
58 * for different servers will become rather complex and difficult to automate.
59 * </p>
60 * <p>
61 * The IsolatedLog4JLogger solves these problems by routing all logging through a statically
62 * configured ContextClassLoader isolated LoggerRepository.
63 * </p>
64 * Using this class requires a commons-logging.properties file in the WEB-INF/classes
65 * folder containing:
66 * <pre>
67 * org.apache.commons.logging.Log=org.apache.jetspeed.util.IsolatedLog4JLogger
68 * </pre>
69 * </p>
70 * <p>
71 * During web application initialization, preferably from a ServletContextListener or
72 * a Servlet init method loaded with a load-on-startup value of 0 (zero), a new
73 * ContextClassLoader (e.g. web application) specific LoggerRepository as well as
74 * the initialization of Log4J should be configured as follows:
75 * <pre>
76 * Properties p = new Properties();
77 * p.load(new FileInputStream(log4jFile));
78 * // Create a new LoggerRepository
79 * Hierarchy h = new Hierarchy(new RootCategory(Level.INFO));
80 * // Configure the LoggerRepository with our own Log4J configuration
81 * new PropertyConfigurator().doConfigure(p,h);
82 * // set the LoggerRepository to be used for the current ContextClassLoader
83 * IsolatedLog4JLogger.setHierarchy(h);
84 * </pre>
85 * Instead of using a PropertyConfigurator a DomConfigurator could be used likewise.
86 * </p>
87 * <p>
88 * TODO: It might be useful to have this utility class available for usage by Portlet
89 * Applications too. Because this class <em>must</em> be included within a web application
90 * classpath, a separate jetspeed-tools or jetspeed-utils library will have to be created
91 * for it (and possibly other utility classes as well) which then can be put in the web
92 * application lib folder.
93 * </p>
94 * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
95 * @version $Id: IsolatedLog4JLogger.java 531463 2007-04-23 13:35:58Z taylor $
96 */
97 public class IsolatedLog4JLogger implements Log
98 {
99 private static Hierarchy hierarchy;
100 private static HashMap notIsolatedLoggers = new HashMap();
101
102 private Log4JLogger logger;
103
104 public static void setHierarchy(Hierarchy hierarchy)
105 {
106 synchronized (IsolatedLog4JLogger.class)
107 {
108 if ( IsolatedLog4JLogger.hierarchy == null )
109 {
110 IsolatedLog4JLogger.hierarchy = hierarchy;
111 if ( notIsolatedLoggers.size() > 0 )
112 {
113
114
115
116
117
118
119 Iterator iter = notIsolatedLoggers.entrySet().iterator();
120 while (iter.hasNext())
121 {
122 Map.Entry entry = (Map.Entry)iter.next();
123 IsolatedLog4JLogger logger = (IsolatedLog4JLogger)entry.getKey();
124 logger.setLogger(new Log4JLogger(hierarchy.getLogger((String)entry.getValue())));
125 }
126 }
127 notIsolatedLoggers = null;
128 }
129 }
130 }
131
132 public IsolatedLog4JLogger(String name)
133 {
134 synchronized (IsolatedLog4JLogger.class)
135 {
136 if ( hierarchy == null )
137 {
138
139
140
141
142 logger = new Log4JLogger(name);
143 notIsolatedLoggers.put(this,name);
144 }
145 else
146 {
147 logger = new Log4JLogger(hierarchy.getLogger(name));
148 }
149 }
150 }
151
152 private void setLogger(Log4JLogger logger)
153 {
154 this.logger = logger;
155 }
156
157 private Log4JLogger getLogger()
158 {
159 return logger;
160 }
161
162 public void debug(Object arg0)
163 {
164 Log4JLogger logger = getLogger();
165 if ( logger != null )
166 {
167 logger.debug(arg0);
168 }
169 }
170 public void debug(Object arg0, Throwable arg1)
171 {
172 Log4JLogger logger = getLogger();
173 if ( logger != null )
174 {
175 logger.debug(arg0,arg1);
176 }
177 }
178 public boolean equals(Object obj)
179 {
180 Log4JLogger logger = getLogger();
181 return logger != null ? logger.equals(obj) : false;
182 }
183 public void error(Object arg0)
184 {
185 Log4JLogger logger = getLogger();
186 if ( logger != null )
187 {
188 logger.error(arg0);
189 }
190 }
191 public void error(Object arg0, Throwable arg1)
192 {
193 Log4JLogger logger = getLogger();
194 if ( logger != null )
195 {
196 logger.error(arg0, arg1);
197 }
198 }
199 public void fatal(Object arg0)
200 {
201 Log4JLogger logger = getLogger();
202 if ( logger != null )
203 {
204 logger.fatal(arg0);
205 }
206 }
207 public void fatal(Object arg0, Throwable arg1)
208 {
209 Log4JLogger logger = getLogger();
210 if ( logger != null )
211 {
212 logger.fatal(arg0, arg1);
213 }
214 }
215 public void info(Object arg0)
216 {
217 Log4JLogger logger = getLogger();
218 if ( logger != null )
219 {
220 logger.info(arg0);
221 }
222 }
223 public void info(Object arg0, Throwable arg1)
224 {
225 Log4JLogger logger = getLogger();
226 if ( logger != null )
227 {
228 logger.info(arg0, arg1);
229 }
230 }
231 public boolean isDebugEnabled()
232 {
233 Log4JLogger logger = getLogger();
234 return logger != null ? logger.isDebugEnabled() : false;
235 }
236 public boolean isErrorEnabled()
237 {
238 Log4JLogger logger = getLogger();
239 return logger != null ? logger.isErrorEnabled() : false;
240 }
241 public boolean isFatalEnabled()
242 {
243 Log4JLogger logger = getLogger();
244 return logger != null ? logger.isFatalEnabled() : false;
245 }
246 public boolean isInfoEnabled()
247 {
248 Log4JLogger logger = getLogger();
249 return logger != null ? logger.isInfoEnabled() : false;
250 }
251 public boolean isTraceEnabled()
252 {
253 Log4JLogger logger = getLogger();
254 return logger != null ? logger.isTraceEnabled() : false;
255 }
256 public boolean isWarnEnabled()
257 {
258 Log4JLogger logger = getLogger();
259 return logger != null ? logger.isWarnEnabled() : false;
260 }
261 public String toString()
262 {
263 Log4JLogger logger = getLogger();
264 return logger != null ? logger.toString() : null;
265 }
266 public void trace(Object arg0)
267 {
268 Log4JLogger logger = getLogger();
269 if ( logger != null )
270 {
271 logger.trace(arg0);
272 }
273 }
274 public void trace(Object arg0, Throwable arg1)
275 {
276 Log4JLogger logger = getLogger();
277 if ( logger != null )
278 {
279 logger.trace(arg0, arg1);
280 }
281 }
282 public void warn(Object arg0)
283 {
284 Log4JLogger logger = getLogger();
285 if ( logger != null )
286 {
287 logger.warn(arg0);
288 }
289 }
290 public void warn(Object arg0, Throwable arg1)
291 {
292 Log4JLogger logger = getLogger();
293 if ( logger != null )
294 {
295 logger.warn(arg0, arg1);
296 }
297 }
298 }