001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package de.schlund.pfixxml.util.logging;
020:
021: import java.lang.reflect.InvocationTargetException;
022: import java.lang.reflect.Method;
023: import java.util.Collections;
024: import java.util.HashMap;
025: import java.util.Map;
026: import java.util.Properties;
027:
028: import javax.servlet.ServletContext;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.apache.log4j.Logger;
033: import org.apache.log4j.Priority;
034: import org.apache.log4j.PropertyConfigurator;
035:
036: /**
037: * Utility class used by ProxyLogObject and ProxyLogAppender.
038: * Does the actual logging work by selecting the right mean to log
039: * through (log4j, commons-logging, jdk-logging, servlet context logging).
040: *
041: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
042: */
043: public class ProxyLogUtil {
044: private Class<?> clFactoryClass = null;
045:
046: private Object clFactoryObject = null;
047:
048: private Method mClGetInstance;
049:
050: private ServletContext servletContext = null;
051:
052: private Map<String, Object> clLoggerCache = Collections
053: .synchronizedMap(new HashMap<String, Object>());
054:
055: private Map<String, Object> l4jLoggerCache = Collections
056: .synchronizedMap(new HashMap<String, Object>());
057:
058: // log4j reflection stuff
059: private Method mLog4jTrace;
060:
061: private Method mLog4jTraceWithEx;
062:
063: private Method mLog4jIsTrace;
064:
065: private Method mLog4jDebug;
066:
067: private Method mLog4jDebugWithEx;
068:
069: private Method mLog4jIsDebug;
070:
071: private Method mLog4jInfo;
072:
073: private Method mLog4jInfoWithEx;
074:
075: private Method mLog4jIsInfo;
076:
077: private Method mLog4jWarn;
078:
079: private Method mLog4jWarnWithEx;
080:
081: private Method mLog4jError;
082:
083: private Method mLog4jErrorWithEx;
084:
085: private Method mLog4jFatal;
086:
087: private Method mLog4jFatalWithEx;
088:
089: private Method mLog4jGetLogger;
090:
091: private Method mLog4jIsEnabled;
092:
093: private Object log4jPriorityWarn;
094:
095: private Object log4jPriorityError;
096:
097: private Object log4jPriorityFatal;
098:
099: // commons-logging reflection stuff
100: private Method mClTrace;
101:
102: private Method mClTraceWithEx;
103:
104: private Method mClIsTrace;
105:
106: private Method mClDebug;
107:
108: private Method mClDebugWithEx;
109:
110: private Method mClIsDebug;
111:
112: private Method mClInfo;
113:
114: private Method mClInfoWithEx;
115:
116: private Method mClIsInfo;
117:
118: private Method mClWarn;
119:
120: private Method mClWarnWithEx;
121:
122: private Method mClIsWarn;
123:
124: private Method mClError;
125:
126: private Method mClErrorWithEx;
127:
128: private Method mClIsError;
129:
130: private Method mClFatal;
131:
132: private Method mClFatalWithEx;
133:
134: private Method mClIsFatal;
135:
136: // Generic stuff
137:
138: private boolean haveCl = false;
139:
140: private boolean haveLog4j = false;
141:
142: private ThreadLocal<Object> contextLogTestFlag = new ThreadLocal<Object>();
143:
144: private boolean noContextLog = false;
145:
146: private static ProxyLogUtil instance = new ProxyLogUtil();
147:
148: /**
149: * Returns the only instance of this class (singleton pattern)
150: *
151: * @return Instance of this class
152: */
153: public static ProxyLogUtil getInstance() {
154: return instance;
155: }
156:
157: /**
158: * Private constructor to force singleton pattern
159: */
160: private ProxyLogUtil() {
161: ClassLoader clLoader = checkForCl();
162: ClassLoader log4jLoader = checkForLog4j();
163:
164: if (clLoader != null) {
165: configureForCommonsLogging(clLoader);
166: }
167:
168: if (log4jLoader != null) {
169: configureForLog4j(log4jLoader);
170: }
171: }
172:
173: /**
174: * Sets the servlet context to use for logging when neither
175: * log4j nor commons-logging are available. However the servlet
176: * context is only used for logging if it does not use
177: * commons-logging or log4j (more precisely OUR instance of them)
178: * to do the logging, as this would result in a logging loop.
179: *
180: * @param context ServletContext to send log messages to
181: */
182: public void setServletContext(ServletContext context) {
183: // Check whether we can log through servlet context without
184: // creating a logging loop
185: this .contextLogTestFlag.set(new Object());
186: // Send test messsage
187: context.log("Testing container logging...");
188: this .contextLogTestFlag.set(null);
189: // If flag is set, the test message was sent back to this
190: // class and we should not use the context to avoid a
191: // logging loop
192: if (!noContextLog) {
193: this .servletContext = context;
194: }
195: }
196:
197: /**
198: * Returns the class loader throgh which the container version
199: * of commons-logging can be loaded. If commons-logging is
200: * not present in the container, <code>null</code> is returned.
201: *
202: * @return class loader another instance of commons-logging was
203: * loaded with or <code>null</code> if no such class
204: * loader is available
205: */
206: private ClassLoader checkForCl() {
207: // Get the classloader OUR version of commons-logging was
208: // loaded with
209: ClassLoader webappLoader = LogFactory.class.getClassLoader();
210: // Get the parent class loader (should usually be the
211: // class loader of the container)
212: ClassLoader cl = webappLoader.getParent();
213: while (cl != null) {
214: // Iterate until a classloader supplying another
215: // version of commons-logging has been found or
216: // we have reached the root (e.g. bootstrap)
217: // class loader
218: Class<?> temp;
219: try {
220: temp = cl.loadClass(LogFactory.class.getName());
221: } catch (ClassNotFoundException e) {
222: cl = cl.getParent();
223: continue;
224: }
225: if (temp != LogFactory.class) {
226: break;
227: }
228: cl = cl.getParent();
229: }
230: return cl;
231: }
232:
233: /**
234: * Returns the class loader throgh which the container version
235: * of log4j can be loaded. If commons-logging is
236: * not present in the container, <code>null</code> is returned.
237: *
238: * @return class loader another instance of log4j was
239: * loaded with or <code>null</code> if no such class
240: * loader is available
241: */
242: private ClassLoader checkForLog4j() {
243: // Look for log4j in container
244: ClassLoader webappLoader = Logger.class.getClassLoader();
245: ClassLoader cl = webappLoader.getParent();
246: while (cl != null) {
247: Class<?> temp;
248: try {
249: temp = cl.loadClass(Logger.class.getName());
250: } catch (ClassNotFoundException e) {
251: cl = cl.getParent();
252: continue;
253: }
254: if (temp != Logger.class) {
255: break;
256: }
257: cl = cl.getParent();
258: }
259: return cl;
260: }
261:
262: /**
263: * Configures log4j to log through this factory. Should only be used
264: * if log4j is not configured by other code.
265: */
266: public void configureLog4jProxy() {
267: // Configure log4j to log through this utility class
268: Properties proptemp = new Properties();
269: proptemp.setProperty("log4j.rootLogger", "ALL, proxy");
270: // Register our special appender which will send all
271: // log messages to this class
272: proptemp.setProperty("log4j.appender.proxy",
273: ProxyLogAppender.class.getName());
274: PropertyConfigurator.configure(proptemp);
275: }
276:
277: /**
278: * Configure this class to log through log4j
279: *
280: * @param classloader class loader to use for loading
281: * the instance of log4j which should be used to
282: * do the actual logging
283: */
284: private void configureForLog4j(ClassLoader classloader) {
285: try {
286: // Make sure all work inside parent log4j is done using its own
287: // classloader (static initializations here)
288: ClassLoader ctxLoader = Thread.currentThread()
289: .getContextClassLoader();
290: Thread.currentThread().setContextClassLoader(classloader);
291:
292: Class<?> log4jLogger;
293: Class<?> log4jPriority;
294: try {
295: log4jLogger = classloader.loadClass(Logger.class
296: .getName());
297: log4jPriority = classloader.loadClass(Priority.class
298: .getName());
299: } finally {
300: // Set the old context classloader again
301: Thread.currentThread().setContextClassLoader(ctxLoader);
302: }
303:
304: // Use reflection to retrieve the various methods we
305: // need to do the logging.
306: // Remember: We have to do all stuff by reflection
307: // because we are not using the log4j instance which was
308: // loaded by OUR classloader, but the log4j instance
309: // loaded by the container.
310: mLog4jGetLogger = log4jLogger.getMethod("getLogger",
311: new Class[] { String.class });
312:
313: mLog4jDebug = log4jLogger.getMethod("debug",
314: new Class[] { Object.class });
315: mLog4jInfo = log4jLogger.getMethod("info",
316: new Class[] { Object.class });
317: mLog4jWarn = log4jLogger.getMethod("warn",
318: new Class[] { Object.class });
319: mLog4jError = log4jLogger.getMethod("error",
320: new Class[] { Object.class });
321: mLog4jFatal = log4jLogger.getMethod("fatal",
322: new Class[] { Object.class });
323: mLog4jDebugWithEx = log4jLogger.getMethod("debug",
324: new Class[] { Object.class, Throwable.class });
325: mLog4jInfoWithEx = log4jLogger.getMethod("info",
326: new Class[] { Object.class, Throwable.class });
327: mLog4jWarnWithEx = log4jLogger.getMethod("warn",
328: new Class[] { Object.class, Throwable.class });
329: mLog4jErrorWithEx = log4jLogger.getMethod("error",
330: new Class[] { Object.class, Throwable.class });
331: mLog4jFatalWithEx = log4jLogger.getMethod("fatal",
332: new Class[] { Object.class, Throwable.class });
333: mLog4jIsDebug = log4jLogger.getMethod("isDebugEnabled",
334: new Class[0]);
335: mLog4jIsInfo = log4jLogger.getMethod("isInfoEnabled",
336: new Class[0]);
337:
338: // Log4j has no convenience methods for this priorities
339: log4jPriorityWarn = log4jPriority.getField("WARN")
340: .get(null);
341: log4jPriorityError = log4jPriority.getField("ERROR").get(
342: null);
343: log4jPriorityFatal = log4jPriority.getField("FATAL").get(
344: null);
345: mLog4jIsEnabled = log4jLogger.getMethod("isEnabledFor",
346: new Class[] { log4jPriority });
347:
348: try {
349: mLog4jTrace = log4jLogger.getMethod("trace",
350: new Class[] { Object.class });
351: mLog4jTraceWithEx = log4jLogger.getMethod("trace",
352: new Class[] { Object.class, Throwable.class });
353: mLog4jIsTrace = log4jLogger.getMethod("isTraceEnabled",
354: new Class[0]);
355: } catch (NoSuchMethodException e) {
356: // trace() is not implemented in log4j <1.2.12
357: mLog4jTrace = mLog4jDebug;
358: mLog4jTraceWithEx = mLog4jDebugWithEx;
359: mLog4jIsTrace = mLog4jIsDebug;
360: }
361:
362: } catch (ClassNotFoundException e) {
363: throw new RuntimeException(e);
364: } catch (SecurityException e) {
365: throw new RuntimeException(e);
366: } catch (NoSuchMethodException e) {
367: throw new RuntimeException(e);
368: } catch (IllegalArgumentException e) {
369: throw new RuntimeException(e);
370: } catch (IllegalAccessException e) {
371: throw new RuntimeException(e);
372: } catch (NoSuchFieldException e) {
373: throw new RuntimeException(e);
374: }
375:
376: haveLog4j = true;
377: }
378:
379: /**
380: * Configures this class for use with commons-logging.
381: *
382: * @param classloader Class loader to load commons-logging trough
383: */
384: private void configureForCommonsLogging(ClassLoader classloader) {
385: // This method works similar to configureForLog4j()
386: try {
387: // Make sure all work inside parent log4j is done using its own
388: // classloader (static initializations here)
389: ClassLoader ctxLoader = Thread.currentThread()
390: .getContextClassLoader();
391: Thread.currentThread().setContextClassLoader(classloader);
392:
393: Class<?> logClass;
394: try {
395: clFactoryClass = classloader.loadClass(LogFactory.class
396: .getName());
397: logClass = classloader.loadClass(Log.class.getName());
398: Method clGetFactory = clFactoryClass.getMethod(
399: "getFactory", new Class[0]);
400: clFactoryObject = clGetFactory.invoke(null,
401: new Object[0]);
402: } finally {
403: // Set the old context classloader again
404: Thread.currentThread().setContextClassLoader(ctxLoader);
405: }
406:
407: mClGetInstance = clFactoryClass.getMethod("getInstance",
408: new Class[] { String.class });
409: mClTrace = logClass.getMethod("trace",
410: new Class[] { Object.class });
411: mClDebug = logClass.getMethod("debug",
412: new Class[] { Object.class });
413: mClInfo = logClass.getMethod("info",
414: new Class[] { Object.class });
415: mClWarn = logClass.getMethod("warn",
416: new Class[] { Object.class });
417: mClError = logClass.getMethod("error",
418: new Class[] { Object.class });
419: mClFatal = logClass.getMethod("fatal",
420: new Class[] { Object.class });
421: mClTraceWithEx = logClass.getMethod("trace", new Class[] {
422: Object.class, Throwable.class });
423: mClDebugWithEx = logClass.getMethod("debug", new Class[] {
424: Object.class, Throwable.class });
425: mClInfoWithEx = logClass.getMethod("info", new Class[] {
426: Object.class, Throwable.class });
427: mClWarnWithEx = logClass.getMethod("warn", new Class[] {
428: Object.class, Throwable.class });
429: mClErrorWithEx = logClass.getMethod("error", new Class[] {
430: Object.class, Throwable.class });
431: mClFatalWithEx = logClass.getMethod("fatal", new Class[] {
432: Object.class, Throwable.class });
433: mClIsTrace = logClass.getMethod("isTraceEnabled",
434: new Class[0]);
435: mClIsDebug = logClass.getMethod("isDebugEnabled",
436: new Class[0]);
437: mClIsInfo = logClass.getMethod("isInfoEnabled",
438: new Class[0]);
439: mClIsWarn = logClass.getMethod("isWarnEnabled",
440: new Class[0]);
441: mClIsError = logClass.getMethod("isErrorEnabled",
442: new Class[0]);
443: mClIsFatal = logClass.getMethod("isFatalEnabled",
444: new Class[0]);
445: } catch (ClassNotFoundException e) {
446: throw new RuntimeException(e);
447: } catch (SecurityException e) {
448: throw new RuntimeException(e);
449: } catch (NoSuchMethodException e) {
450: throw new RuntimeException(e);
451: } catch (IllegalArgumentException e) {
452: throw new RuntimeException(e);
453: } catch (IllegalAccessException e) {
454: throw new RuntimeException(e);
455: } catch (InvocationTargetException e) {
456: throw new RuntimeException(e);
457: }
458:
459: haveCl = true;
460: }
461:
462: void doLogGeneric(String name, Level level, Object msg) {
463: // Check for test flag set in setServletContext()
464: if (this .contextLogTestFlag.get() != null) {
465: // Test flag is set, so we got here when calling
466: // ServletContext#log - so we should not use
467: // the context for logging
468: this .noContextLog = true;
469: return;
470: }
471:
472: if (haveLog4j) {
473: // Prefer log4j
474: doLogLog4j(name, level, msg);
475: } else if (haveCl) {
476: // Then use commons-logging
477: doLogCl(name, level, msg);
478: } else if (noContextLog) {
479: // If neither log4j nor commons-logging are available,
480: // and context cannot be used for logging, use JDK logging
481: doLogJdk14(name, level, msg);
482: } else {
483: // Otherwise use servlet context for logging
484: if (servletContext != null
485: && (level == Level.WARN || level == Level.ERROR || level == Level.FATAL)) {
486: servletContext.log("[" + level + "] " + name + ": "
487: + msg);
488: }
489: }
490: }
491:
492: void doLogGeneric(String name, Level level, Object msg, Throwable ex) {
493: // This method does nearly the same as the other
494: // doLogGeneric() method but takes an exception as
495: // as an additional argument
496: if (this .contextLogTestFlag.get() != null) {
497: this .noContextLog = true;
498: return;
499: }
500:
501: if (haveLog4j) {
502: doLogLog4j(name, level, msg, ex);
503: } else if (haveCl) {
504: doLogCl(name, level, msg, ex);
505: } else if (noContextLog) {
506: doLogJdk14(name, level, msg, ex);
507: } else {
508: if (servletContext != null
509: && (level == Level.WARN || level == Level.ERROR || level == Level.FATAL)) {
510: servletContext.log("[" + level + "] " + name + ": "
511: + msg, ex);
512: }
513: }
514: }
515:
516: boolean doCheckEnabledGeneric(String name, Level level) {
517: // Determine whether logging is enabled for
518: // a specific level. Select the logging system
519: // the same way doLogGeneric() does.
520: if (haveLog4j) {
521: return doCheckEnabledLog4j(name, level);
522: } else if (haveCl) {
523: return doCheckEnabledCl(name, level);
524: } else if (noContextLog) {
525: return doCheckEnabledJdk14(name, level);
526: } else {
527: if (level == Level.WARN || level == Level.ERROR
528: || level == Level.FATAL) {
529: return true;
530: } else {
531: return false;
532: }
533: }
534: }
535:
536: void doLogJdk14(String name, Level level, Object msg) {
537: java.util.logging.Logger logger = java.util.logging.Logger
538: .getLogger(name);
539: if (level == Level.FATAL || level == Level.ERROR) {
540: logger.log(java.util.logging.Level.SEVERE, msg.toString());
541: } else if (level == Level.WARN) {
542: logger.log(java.util.logging.Level.WARNING, msg.toString());
543: } else if (level == Level.INFO) {
544: logger.log(java.util.logging.Level.INFO, msg.toString());
545: } else if (level == Level.DEBUG) {
546: logger.log(java.util.logging.Level.FINE, msg.toString());
547: } else if (level == Level.TRACE) {
548: logger.log(java.util.logging.Level.FINER, msg.toString());
549: }
550: }
551:
552: void doLogJdk14(String name, Level level, Object msg, Throwable ex) {
553: java.util.logging.Logger logger = java.util.logging.Logger
554: .getLogger(name);
555: if (level == Level.FATAL || level == Level.ERROR) {
556: logger.log(java.util.logging.Level.SEVERE, msg.toString(),
557: ex);
558: } else if (level == Level.WARN) {
559: logger.log(java.util.logging.Level.WARNING, msg.toString(),
560: ex);
561: } else if (level == Level.INFO) {
562: logger
563: .log(java.util.logging.Level.INFO, msg.toString(),
564: ex);
565: } else if (level == Level.DEBUG) {
566: logger
567: .log(java.util.logging.Level.FINE, msg.toString(),
568: ex);
569: } else if (level == Level.TRACE) {
570: logger.log(java.util.logging.Level.FINER, msg.toString(),
571: ex);
572: }
573: }
574:
575: boolean doCheckEnabledJdk14(String name, Level level) {
576: java.util.logging.Logger logger = java.util.logging.Logger
577: .getLogger(name);
578: if (level == Level.FATAL || level == Level.ERROR) {
579: return logger.isLoggable(java.util.logging.Level.SEVERE);
580: } else if (level == Level.WARN) {
581: return logger.isLoggable(java.util.logging.Level.WARNING);
582: } else if (level == Level.INFO) {
583: return logger.isLoggable(java.util.logging.Level.INFO);
584: } else if (level == Level.DEBUG) {
585: return logger.isLoggable(java.util.logging.Level.FINE);
586: } else if (level == Level.TRACE) {
587: return logger.isLoggable(java.util.logging.Level.FINER);
588: } else {
589: return false;
590: }
591: }
592:
593: void doLogLog4j(String name, Level level, Object msg) {
594: if (!haveLog4j) {
595: // If log4j is not configured, we have to use
596: // one the availabele logging systems
597: doLogGeneric(name, level, msg);
598: return;
599: }
600:
601: // Change and reset context class loader
602: ClassLoader ctxLoader = Thread.currentThread()
603: .getContextClassLoader();
604: Thread.currentThread().setContextClassLoader(
605: mLog4jTrace.getDeclaringClass().getClassLoader());
606:
607: Object logObj = getLog4jLogger(name);
608: try {
609: if (level == Level.TRACE) {
610: mLog4jTrace.invoke(logObj, new Object[] { msg });
611: } else if (level == Level.DEBUG) {
612: mLog4jDebug.invoke(logObj, new Object[] { msg });
613: } else if (level == Level.INFO) {
614: mLog4jInfo.invoke(logObj, new Object[] { msg });
615: } else if (level == Level.WARN) {
616: mLog4jWarn.invoke(logObj, new Object[] { msg });
617: } else if (level == Level.ERROR) {
618: mLog4jError.invoke(logObj, new Object[] { msg });
619: } else if (level == Level.FATAL) {
620: mLog4jFatal.invoke(logObj, new Object[] { msg });
621: }
622: } catch (IllegalAccessException e) {
623: throw new RuntimeException(e);
624: } catch (InvocationTargetException e) {
625: throw new RuntimeException(e);
626: } finally {
627: Thread.currentThread().setContextClassLoader(ctxLoader);
628: }
629: }
630:
631: void doLogLog4j(String name, Level level, Object msg, Throwable ex) {
632: if (!haveLog4j) {
633: // If log4j is not configured, we have to use
634: // one the availabele logging systems
635: doLogGeneric(name, level, msg, ex);
636: return;
637: }
638:
639: // Change and reset context class loader
640: ClassLoader ctxLoader = Thread.currentThread()
641: .getContextClassLoader();
642: Thread.currentThread().setContextClassLoader(
643: mLog4jTraceWithEx.getDeclaringClass().getClassLoader());
644:
645: Object logObj = getLog4jLogger(name);
646: try {
647: if (level == Level.TRACE) {
648: mLog4jTraceWithEx.invoke(logObj,
649: new Object[] { msg, ex });
650: } else if (level == Level.DEBUG) {
651: mLog4jDebugWithEx.invoke(logObj,
652: new Object[] { msg, ex });
653: } else if (level == Level.INFO) {
654: mLog4jInfoWithEx.invoke(logObj,
655: new Object[] { msg, ex });
656: } else if (level == Level.WARN) {
657: mLog4jWarnWithEx.invoke(logObj,
658: new Object[] { msg, ex });
659: } else if (level == Level.ERROR) {
660: mLog4jErrorWithEx.invoke(logObj,
661: new Object[] { msg, ex });
662: } else if (level == Level.FATAL) {
663: mLog4jFatalWithEx.invoke(logObj,
664: new Object[] { msg, ex });
665: }
666: } catch (IllegalAccessException e) {
667: throw new RuntimeException(e);
668: } catch (InvocationTargetException e) {
669: throw new RuntimeException(e);
670: } finally {
671: Thread.currentThread().setContextClassLoader(ctxLoader);
672: }
673: }
674:
675: boolean doCheckEnabledLog4j(String name, Level level) {
676: if (!haveLog4j) {
677: // If log4j is not configured, we have to use
678: // one the availabele logging systems
679: return doCheckEnabledGeneric(name, level);
680: }
681:
682: // Change and reset context class loader
683: ClassLoader ctxLoader = Thread.currentThread()
684: .getContextClassLoader();
685: Thread.currentThread().setContextClassLoader(
686: mLog4jIsTrace.getDeclaringClass().getClassLoader());
687:
688: Object retval = null;
689: Object logObj = getLog4jLogger(name);
690: try {
691: if (level == Level.TRACE) {
692: retval = mLog4jIsTrace.invoke(logObj, new Object[0]);
693: } else if (level == Level.DEBUG) {
694: retval = mLog4jIsDebug.invoke(logObj, new Object[0]);
695: } else if (level == Level.INFO) {
696: retval = mLog4jIsInfo.invoke(logObj, new Object[0]);
697: } else if (level == Level.WARN) {
698: retval = mLog4jIsEnabled.invoke(logObj,
699: new Object[] { log4jPriorityWarn });
700: } else if (level == Level.ERROR) {
701: retval = mLog4jIsEnabled.invoke(logObj,
702: new Object[] { log4jPriorityError });
703: } else if (level == Level.FATAL) {
704: retval = mLog4jIsEnabled.invoke(logObj,
705: new Object[] { log4jPriorityFatal });
706: }
707: } catch (IllegalAccessException e) {
708: throw new RuntimeException(e);
709: } catch (InvocationTargetException e) {
710: throw new RuntimeException(e);
711: } finally {
712: Thread.currentThread().setContextClassLoader(ctxLoader);
713: }
714:
715: return ((Boolean) retval).booleanValue();
716: }
717:
718: private Object getLog4jLogger(String name) {
719: // Return a logger for a specific name
720: // Note: This has all to be done using the
721: // right classloader or we will run in funny
722: // problems...
723: Object logObj;
724: logObj = l4jLoggerCache.get(name);
725: if (logObj == null) {
726: // Change and reset context class loader
727: ClassLoader ctxLoader = Thread.currentThread()
728: .getContextClassLoader();
729: Thread.currentThread().setContextClassLoader(
730: mLog4jGetLogger.getDeclaringClass()
731: .getClassLoader());
732:
733: try {
734: logObj = mLog4jGetLogger.invoke(null,
735: new Object[] { name });
736: } catch (IllegalArgumentException e) {
737: throw new RuntimeException(e);
738: } catch (IllegalAccessException e) {
739: throw new RuntimeException(e);
740: } catch (InvocationTargetException e) {
741: throw new RuntimeException(e);
742: } finally {
743: Thread.currentThread().setContextClassLoader(ctxLoader);
744: }
745: l4jLoggerCache.put(name, logObj);
746: }
747:
748: return logObj;
749: }
750:
751: void doLogCl(String name, Level level, Object msg) {
752: // Similar to doLogLog4j()
753: if (!haveCl) {
754: doLogGeneric(name, level, msg);
755: return;
756: }
757:
758: // Change and reset context class loader
759: ClassLoader ctxLoader = Thread.currentThread()
760: .getContextClassLoader();
761: Thread.currentThread().setContextClassLoader(
762: mClTrace.getDeclaringClass().getClassLoader());
763:
764: Object logObj = getClLogger(name);
765: try {
766: if (level == Level.TRACE) {
767: mClTrace.invoke(logObj, new Object[] { msg });
768: } else if (level == Level.DEBUG) {
769: mClDebug.invoke(logObj, new Object[] { msg });
770: } else if (level == Level.INFO) {
771: mClInfo.invoke(logObj, new Object[] { msg });
772: } else if (level == Level.WARN) {
773: mClWarn.invoke(logObj, new Object[] { msg });
774: } else if (level == Level.ERROR) {
775: mClError.invoke(logObj, new Object[] { msg });
776: } else if (level == Level.FATAL) {
777: mClFatal.invoke(logObj, new Object[] { msg });
778: }
779: } catch (IllegalAccessException e) {
780: throw new RuntimeException(e);
781: } catch (InvocationTargetException e) {
782: throw new RuntimeException(e);
783: } finally {
784: Thread.currentThread().setContextClassLoader(ctxLoader);
785: }
786: }
787:
788: void doLogCl(String name, Level level, Object msg, Throwable ex) {
789: // Similar to doLogLog4j()
790: if (!haveCl) {
791: doLogGeneric(name, level, msg, ex);
792: return;
793: }
794:
795: // Change and reset context class loader
796: ClassLoader ctxLoader = Thread.currentThread()
797: .getContextClassLoader();
798: Thread.currentThread().setContextClassLoader(
799: mClTraceWithEx.getDeclaringClass().getClassLoader());
800:
801: Object logObj = getClLogger(name);
802: try {
803: if (level == Level.TRACE) {
804: mClTraceWithEx.invoke(logObj, new Object[] { msg, ex });
805: } else if (level == Level.DEBUG) {
806: mClDebugWithEx.invoke(logObj, new Object[] { msg, ex });
807: } else if (level == Level.INFO) {
808: mClInfoWithEx.invoke(logObj, new Object[] { msg, ex });
809: } else if (level == Level.WARN) {
810: mClWarnWithEx.invoke(logObj, new Object[] { msg, ex });
811: } else if (level == Level.ERROR) {
812: mClErrorWithEx.invoke(logObj, new Object[] { msg, ex });
813: } else if (level == Level.FATAL) {
814: mClFatalWithEx.invoke(logObj, new Object[] { msg, ex });
815: }
816: } catch (IllegalAccessException e) {
817: throw new RuntimeException(e);
818: } catch (InvocationTargetException e) {
819: throw new RuntimeException(e);
820: } finally {
821: Thread.currentThread().setContextClassLoader(ctxLoader);
822: }
823: }
824:
825: boolean doCheckEnabledCl(String name, Level level) {
826: // Similar to doCheckEnabledLog4j()
827: if (!haveCl) {
828: return doCheckEnabledGeneric(name, level);
829: }
830:
831: // Change and reset context class loader
832: ClassLoader ctxLoader = Thread.currentThread()
833: .getContextClassLoader();
834: Thread.currentThread().setContextClassLoader(
835: mClIsTrace.getDeclaringClass().getClassLoader());
836:
837: Object retval = null;
838: Object logObj = getClLogger(name);
839: try {
840: if (level == Level.TRACE) {
841: retval = mClIsTrace.invoke(logObj, new Object[0]);
842: } else if (level == Level.DEBUG) {
843: retval = mClIsDebug.invoke(logObj, new Object[0]);
844: } else if (level == Level.INFO) {
845: retval = mClIsInfo.invoke(logObj, new Object[0]);
846: } else if (level == Level.WARN) {
847: retval = mClIsWarn.invoke(logObj, new Object[0]);
848: } else if (level == Level.ERROR) {
849: retval = mClIsError.invoke(logObj, new Object[0]);
850: } else if (level == Level.FATAL) {
851: retval = mClIsFatal.invoke(logObj, new Object[0]);
852: }
853: } catch (IllegalAccessException e) {
854: throw new RuntimeException(e);
855: } catch (InvocationTargetException e) {
856: throw new RuntimeException(e);
857: } finally {
858: Thread.currentThread().setContextClassLoader(ctxLoader);
859: }
860:
861: return ((Boolean) retval).booleanValue();
862: }
863:
864: private Object getClLogger(String name) {
865: // Similar to getLog4jLogger()
866: Object logObj;
867: logObj = clLoggerCache.get(name);
868: if (logObj == null) {
869: // Change and reset context class loader
870: ClassLoader ctxLoader = Thread.currentThread()
871: .getContextClassLoader();
872: Thread.currentThread().setContextClassLoader(
873: clFactoryObject.getClass().getClassLoader());
874:
875: try {
876: logObj = mClGetInstance.invoke(clFactoryObject,
877: new Object[] { name });
878: } catch (IllegalArgumentException e) {
879: throw new RuntimeException(e);
880: } catch (IllegalAccessException e) {
881: throw new RuntimeException(e);
882: } catch (InvocationTargetException e) {
883: throw new RuntimeException(e);
884: } finally {
885: Thread.currentThread().setContextClassLoader(ctxLoader);
886: }
887: clLoggerCache.put(name, logObj);
888: }
889:
890: return logObj;
891: }
892:
893: boolean isConfiguredForCl() {
894: // This method is used by ProxyLogFactory in order do
895: // determine wheter it shall create logger that log through
896: // this class or use the default log4j loggers, which will
897: // use our log4j instance for logging (this is the default).
898: return haveCl;
899: }
900:
901: /**
902: * Enum class specifying all log levels
903: *
904: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
905: */
906: enum Level {
907: TRACE, DEBUG, INFO, WARN, ERROR, FATAL
908: }
909:
910: }
|