From f0e9b049351054fa0f4e8236a4556f7e32ff513f Mon Sep 17 00:00:00 2001 From: Elias Ross Date: Tue, 5 Apr 2011 17:10:49 -0700 Subject: [PATCH] Create custom appender; use it to output messages if custom logger is used --- pom.xml | 9 ++ .../org/jboss/logmanager/log4j/BridgeAppender.java | 74 ++++++++++++++++ .../jboss/logmanager/log4j/BridgeRepository.java | 43 ++++++++- .../org/jboss/logmanager/log4j/LoggerTests.java | 93 ++++++++++++++++++++ 4 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/jboss/logmanager/log4j/BridgeAppender.java create mode 100644 src/test/java/org/jboss/logmanager/log4j/LoggerTests.java diff --git a/pom.xml b/pom.xml index e6d127b..7b6034b 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,15 @@ + + + org.testng + testng + 5.8 + jdk15 + test + + diff --git a/src/main/java/org/jboss/logmanager/log4j/BridgeAppender.java b/src/main/java/org/jboss/logmanager/log4j/BridgeAppender.java new file mode 100644 index 0000000..0ffb98c --- /dev/null +++ b/src/main/java/org/jboss/logmanager/log4j/BridgeAppender.java @@ -0,0 +1,74 @@ +package org.jboss.logmanager.log4j; + +import java.util.logging.Level; + +import org.apache.log4j.Appender; +import org.apache.log4j.Layout; +import org.apache.log4j.spi.ErrorHandler; +import org.apache.log4j.spi.Filter; +import org.apache.log4j.spi.LoggingEvent; +import org.apache.log4j.spi.ThrowableInformation; +import org.jboss.logmanager.Logger; + +/** + * Appends messages using a logger; as a way to allow for custom log4j Loggers. + * + * @author Elias Ross + */ +class BridgeAppender implements Appender { + + private final Logger logger; + + public BridgeAppender(Logger logger) { + this.logger = logger; + if (logger == null) + throw new NullPointerException("logger"); + } + + public void addFilter(Filter paramFilter) { + } + + public Filter getFilter() { + return null; + } + + public void clearFilters() { + } + + public void close() { + } + + public void doAppend(LoggingEvent le) { + Level level = LevelMapping.getLevelFor(le.getLevel()); + String message = String.valueOf(le.getMessage()); + ThrowableInformation ti = le.getThrowableInformation(); + Throwable t = ti != null ? ti.getThrowable() : null; + logger.log(level, message, t); + } + + public String getName() { + return logger.getName(); + } + + public void setErrorHandler(ErrorHandler paramErrorHandler) { + } + + public ErrorHandler getErrorHandler() { + return null; + } + + public void setLayout(Layout paramLayout) { + } + + public Layout getLayout() { + return null; + } + + public void setName(String paramString) { + } + + public boolean requiresLayout() { + return false; + } + +} diff --git a/src/main/java/org/jboss/logmanager/log4j/BridgeRepository.java b/src/main/java/org/jboss/logmanager/log4j/BridgeRepository.java index 157051e..05528db 100644 --- a/src/main/java/org/jboss/logmanager/log4j/BridgeRepository.java +++ b/src/main/java/org/jboss/logmanager/log4j/BridgeRepository.java @@ -22,6 +22,9 @@ package org.jboss.logmanager.log4j; +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Enumeration; import java.util.Collections; @@ -39,7 +42,23 @@ import org.jboss.logmanager.LogContext; * A logger repository which returns log4j loggers which bridge to their corresponding LogManager logger. */ public final class BridgeRepository implements LoggerRepository { - private final org.jboss.logmanager.Logger.AttachmentKey reposKey = new org.jboss.logmanager.Logger.AttachmentKey(); + + private static Field categoryRepository; + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + try { + categoryRepository = Category.class.getDeclaredField("repository"); + categoryRepository.setAccessible(true); + } catch (Exception e) { + throw new Error(e); + } + return null; + } + }); + + } + private final org.jboss.logmanager.Logger.AttachmentKey reposKey = new org.jboss.logmanager.Logger.AttachmentKey(); public void addHierarchyEventListener(final HierarchyEventListener listener) { // ignore @@ -64,7 +83,7 @@ public final class BridgeRepository implements LoggerRepository { public Level getThreshold() { return Level.ALL; } - + public Logger getLogger(final String name) { final org.jboss.logmanager.Logger lmLogger = LogContext.getLogContext().getLogger(name); final Logger logger = lmLogger.getAttachment(reposKey); @@ -75,7 +94,23 @@ public final class BridgeRepository implements LoggerRepository { } public Logger getLogger(final String name, final LoggerFactory factory) { - return getLogger(name); + final org.jboss.logmanager.Logger lmLogger = LogContext.getLogContext().getLogger(name); + Logger logger = lmLogger.getAttachment(reposKey); + if (logger != null) { + return logger; + } + + logger = factory.makeNewLoggerInstance(name); + try { + categoryRepository.set(logger, this); + } catch (Exception e) { + throw new RuntimeException(e); + } + logger.setLevel(Level.ALL); + logger.addAppender(new BridgeAppender(lmLogger)); + + Logger appearingLogger = lmLogger.attachIfAbsent(reposKey, logger); + return appearingLogger != null ? appearingLogger : logger; } public Logger getRootLogger() { @@ -92,7 +127,7 @@ public final class BridgeRepository implements LoggerRepository { private Logger create(final org.jboss.logmanager.Logger lmLogger) { final BridgeLogger logger = new BridgeLogger(lmLogger); - final BridgeLogger appearingLogger = lmLogger.attachIfAbsent(reposKey, logger); + final Logger appearingLogger = lmLogger.attachIfAbsent(reposKey, logger); return appearingLogger != null ? appearingLogger : logger; } diff --git a/src/test/java/org/jboss/logmanager/log4j/LoggerTests.java b/src/test/java/org/jboss/logmanager/log4j/LoggerTests.java new file mode 100644 index 0000000..3ffc921 --- /dev/null +++ b/src/test/java/org/jboss/logmanager/log4j/LoggerTests.java @@ -0,0 +1,93 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2009, Red Hat Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ + +package org.jboss.logmanager.log4j; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +import org.apache.log4j.spi.LoggerFactory; +import org.jboss.logmanager.Logger; +import org.jboss.logmanager.log4j.BridgeRepositorySelector; +import org.testng.annotations.Test; +import static org.testng.AssertJUnit.*; + +@Test +public final class LoggerTests implements LoggerFactory { + + static { + System.setProperty("java.util.logging.manager", "org.jboss.logmanager.LogManager"); + new BridgeRepositorySelector().start(); + } + + private final AtomicBoolean ran = new AtomicBoolean(); + private final String cat = getClass().getName(); + private final String factory = "factory"; + + public void testBasic() { + Logger.getLogger(cat).addHandler(new CheckingHandler()); + org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(cat); + logger.info("Hello, world"); + } + + public void testLoggerFactory() { + Logger.getLogger(factory).addHandler(new CheckingHandler()); + org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(factory, this); + logger.info("Hello, world"); + logger.info("Error", new Throwable()); + assertTrue("Right class " + logger, logger instanceof MyLogger); + + logger = org.apache.log4j.Logger.getLogger("different", this); + assertTrue("Right class " + logger, logger instanceof MyLogger); + + } + + class MyLogger extends org.apache.log4j.Logger { + + protected MyLogger(String name) { + super(name); + } + + } + + public org.apache.log4j.Logger makeNewLoggerInstance(String category) { + return new MyLogger(category); + } + + private class CheckingHandler extends Handler { + + public void publish(final LogRecord record) { + if (isLoggable(record)) { + ran.set(true); + } + System.out.println(record.getMessage()); + } + + public void flush() { + } + + public void close() throws SecurityException { + } + } + +} -- 1.7.3.3