Index: src/site/xdoc/manual/layouts.xml.vm
===================================================================
--- src/site/xdoc/manual/layouts.xml.vm (revision 1574084)
+++ src/site/xdoc/manual/layouts.xml.vm (working copy)
@@ -393,6 +393,41 @@
+
ex |exception |throwable
{["none"
|"full"
Index: log4j-api/src/test/java/org/apache/logging/log4j/spi/LoggerOutputStreamTest.java
===================================================================
--- log4j-api/src/test/java/org/apache/logging/log4j/spi/LoggerOutputStreamTest.java (revision 0)
+++ log4j-api/src/test/java/org/apache/logging/log4j/spi/LoggerOutputStreamTest.java (revision 0)
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.spi;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.TestLogger;
+import org.apache.logging.log4j.spi.LoggerOutputStream;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.hamcrest.core.StringStartsWith.startsWith;
+import static org.junit.Assert.*;
+
+@RunWith(Parameterized.class)
+public class LoggerOutputStreamTest {
+ private List results;
+ private LoggerOutputStream stream;
+ private Level level;
+ private String logMessage;
+
+ @Parameterized.Parameters
+ public static Collection data() {
+ return Arrays.asList(
+ new Object[][]{
+ { Level.DEBUG, "debug log string test" },
+ { Level.INFO, "info log string test" },
+ { Level.WARN, "DANGER ZONE" },
+ { Level.ERROR, "MAYDAY! MAYDAY!" },
+ { Level.FATAL, "ABANDON SHIP!" }
+ }
+ );
+ }
+
+ public LoggerOutputStreamTest(final Level level, final String logMessage) {
+ this.level = level;
+ this.logMessage = logMessage;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ TestLogger logger = (TestLogger) LogManager.getLogger();
+ results = logger.getEntries();
+ assertEmpty();
+ stream = new LoggerOutputStream(logger, level);
+ assertEmpty();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ results.clear();
+ }
+
+ private void assertEmpty() {
+ assertTrue("There should be no results yet.", results.isEmpty());
+ }
+
+ private void assertNumResults(int numResults) {
+ assertEquals("Unexpected number of results.", numResults, results.size());
+ }
+
+ private void assertMessageStartsWith(final String message) {
+ assertNumResults(1);
+ final String start = ' ' + level.name() + ' ' + message;
+ assertThat(results.get(0), startsWith(start));
+ }
+
+ @Test
+ public void testWrite_Int() throws Exception {
+ for (byte b : logMessage.getBytes()) {
+ stream.write(b);
+ assertEmpty();
+ }
+ stream.write('\n');
+ assertMessageStartsWith(logMessage);
+ }
+
+ @Test
+ public void testWrite_ByteArray() throws Exception {
+ final byte[] bytes = logMessage.getBytes();
+ stream.write(bytes);
+ assertEmpty();
+ stream.write('\n');
+ assertMessageStartsWith(logMessage);
+ }
+
+ @Test
+ public void testWrite_ByteArray_Offset_Length() throws Exception {
+ final byte[] bytes = logMessage.getBytes();
+ int middle = bytes.length/2;
+ int length = bytes.length - middle;
+ final String right = new String(bytes, middle, length);
+ stream.write(bytes, middle, length);
+ assertEmpty();
+ stream.write('\n');
+ assertMessageStartsWith(right);
+ }
+
+ @Test
+ public void testPrint_Boolean() throws Exception {
+ stream.print(true);
+ assertEmpty();
+ stream.println();
+ assertMessageStartsWith("true");
+ }
+
+ @Test
+ public void testPrint_Character() throws Exception {
+ for (char c : logMessage.toCharArray()) {
+ stream.print(c);
+ assertEmpty();
+ }
+ stream.println();
+ assertMessageStartsWith(logMessage);
+ }
+
+ @Test
+ public void testPrint_Integer() throws Exception {
+ int n = logMessage.codePointAt(0);
+ stream.print(n);
+ assertEmpty();
+ stream.println();
+ assertMessageStartsWith(String.valueOf(n));
+ }
+
+ @Test
+ public void testPrint_CharacterArray() throws Exception {
+ stream.print(logMessage.toCharArray());
+ assertEmpty();
+ stream.println();
+ assertMessageStartsWith(logMessage);
+ }
+
+ @Test
+ public void testPrint_String() throws Exception {
+ stream.print(logMessage);
+ assertEmpty();
+ stream.println();
+ assertMessageStartsWith(logMessage);
+ }
+
+ @Test
+ public void testPrint_Object() throws Exception {
+ final Object o = logMessage;
+ stream.print(o);
+ assertEmpty();
+ stream.println();
+ assertMessageStartsWith(logMessage);
+ }
+
+ @Test
+ public void testPrintf() throws Exception {
+ stream.printf("<<<%s>>>", logMessage);
+ assertEmpty();
+ stream.println();
+ assertMessageStartsWith("<<<" + logMessage);
+ }
+
+ @Test
+ public void testFormat() throws Exception {
+ stream.format("[%s]", logMessage).println();
+ assertMessageStartsWith("[" + logMessage);
+ }
+}
Index: log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java (revision 1574084)
+++ log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java (working copy)
@@ -16,7 +16,6 @@
*/
package org.apache.logging.log4j.spi;
-import java.io.PrintWriter;
import java.io.Serializable;
import org.apache.logging.log4j.Level;
@@ -32,7 +31,7 @@
/**
* Base implementation of a Logger. It is highly recommended that any Logger implementation extend this class.
*/
-public abstract class AbstractLogger implements Logger, Serializable {
+public abstract class AbstractLogger implements Logger, ExtensibleLogger, Serializable {
private static final long serialVersionUID = 2L;
@@ -851,29 +850,6 @@
}
/**
- * Gets a print stream that logs lines to this logger.
- *
- * @param level the logging level
- * @return print stream that logs printed lines to this logger.
- */
- @Override
- public PrintWriter printWriter(final Level level) {
- return new PrintWriter(new LoggerWriter(this, null, level), true);
- }
-
- /**
- * Gets a marked print stream that logs lines to this logger.
- *
- * @param marker the marker data specific to this log statement
- * @param level the logging level
- * @return print stream that logs printed lines to this logger.
- */
- @Override
- public PrintWriter printWriter(Marker marker, Level level) {
- return new PrintWriter(new LoggerWriter(this, marker, level), true);
- }
-
- /**
* Logs a message with the specific Marker at the INFO level.
*
* @param marker the marker data specific to this log statement
@@ -1475,7 +1451,7 @@
* @param data The Message.
* @param t A Throwable or null.
*/
- public abstract void log(Marker marker, String fqcn, Level level, Message data, Throwable t);
+ protected abstract void log(Marker marker, String fqcn, Level level, Message data, Throwable t);
/**
* Logs a formatted message using the specified format string and arguments.
@@ -1965,4 +1941,78 @@
}
}
+ @Override
+ public LoggerExtension extend(Class> extendingClass) {
+ return new Extension(extendingClass.getName());
+ }
+
+ private final class Extension implements LoggerExtension {
+
+ private final String fqcn;
+
+ Extension(String fqcn) {
+ this.fqcn = fqcn;
+ }
+
+ @Override
+ public boolean isEnabled(Level level, Marker marker, Message data, Throwable t) {
+ return AbstractLogger.this.isEnabled(level, marker, data, t);
+ }
+
+ @Override
+ public boolean isEnabled(Level level, Marker marker, Object data, Throwable t) {
+ return AbstractLogger.this.isEnabled(level, marker, data, t);
+ }
+
+ @Override
+ public boolean isEnabled(Level level, Marker marker, String data) {
+ return AbstractLogger.this.isEnabled(level, marker, data);
+ }
+
+ @Override
+ public boolean isEnabled(Level level, Marker marker, String data, Object... p1) {
+ return AbstractLogger.this.isEnabled(level, marker, data, p1);
+ }
+
+ @Override
+ public boolean isEnabled(Level level, Marker marker, String data, Throwable t) {
+ return AbstractLogger.this.isEnabled(level, marker, data, t);
+ }
+
+ @Override
+ public void log(Level level, Marker marker, Message data, Throwable t) {
+ if (AbstractLogger.this.isEnabled(level, marker, data, t)) {
+ AbstractLogger.this.log(marker, fqcn, level, data, t);
+ }
+ }
+
+ @Override
+ public void log(Level level, Marker marker, Object data, Throwable t) {
+ if (AbstractLogger.this.isEnabled(level, marker, data, t)) {
+ AbstractLogger.this.log(marker, fqcn, level, getMessageFactory().newMessage(data), t);
+ }
+ }
+
+ @Override
+ public void log(Level level, Marker marker, String data) {
+ if (AbstractLogger.this.isEnabled(level, marker, data)) {
+ AbstractLogger.this.log(marker, fqcn, level, getMessageFactory().newMessage(data), null);
+ }
+ }
+
+ @Override
+ public void log(Level level, Marker marker, String data, Object... p1) {
+ if (AbstractLogger.this.isEnabled(level, marker, data)) {
+ AbstractLogger.this.log(marker, fqcn, level, getMessageFactory().newMessage(data, p1), null);
+ }
+ }
+
+ @Override
+ public void log(Level level, Marker marker, String data, Throwable t) {
+ if (AbstractLogger.this.isEnabled(level, marker, data)) {
+ AbstractLogger.this.log(marker, fqcn, level, getMessageFactory().newMessage(data), null);
+ }
+ }
+
+ }
}
Index: log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerExtension.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerExtension.java (revision 0)
+++ log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerExtension.java (revision 0)
@@ -0,0 +1,28 @@
+package org.apache.logging.log4j.spi;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.message.Message;
+
+public interface LoggerExtension {
+
+ boolean isEnabled(Level level, Marker marker, Message data, Throwable t);
+
+ boolean isEnabled(Level level, Marker marker, Object data, Throwable t);
+
+ boolean isEnabled(Level level, Marker marker, String data);
+
+ boolean isEnabled(Level level, Marker marker, String data, Object... p1);
+
+ boolean isEnabled(Level level, Marker marker, String data, Throwable t);
+
+ void log(Level level, Marker marker, Message data, Throwable t);
+
+ void log(Level level, Marker marker, Object data, Throwable t);
+
+ void log(Level level, Marker marker, String data);
+
+ void log(Level level, Marker marker, String data, Object... p1);
+
+ void log(Level level, Marker marker, String data, Throwable t);
+}
Index: log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtensibleLogger.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtensibleLogger.java (revision 0)
+++ log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtensibleLogger.java (revision 0)
@@ -0,0 +1,6 @@
+package org.apache.logging.log4j.spi;
+
+
+public interface ExtensibleLogger {
+ public LoggerExtension extend(Class> extensionClass);
+}
Index: log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerWriter.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerWriter.java (revision 1574084)
+++ log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerWriter.java (working copy)
@@ -18,61 +18,117 @@
import java.io.IOException;
import java.io.Writer;
+import java.nio.CharBuffer;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
-import org.apache.logging.log4j.message.Message;
public class LoggerWriter extends Writer {
- private static final String FQCN = LoggerWriter.class.getName();
- private final AbstractLogger logger;
+ private final Writer writer;
+ private final LoggerExtension logger;
private final Level level;
private final Marker marker;
- private final StringBuilder buf = new StringBuilder();
+ private final StringBuilder msg = new StringBuilder();
+ private boolean closed;
- public LoggerWriter(AbstractLogger logger, Marker marker, Level level) {
+ public LoggerWriter(Writer writer, LoggerExtension logger, Level level, Marker marker) {
+ this.writer = writer;
this.logger = logger;
- this.marker = marker;
this.level = level;
+ this.marker = marker;
}
@Override
- public void close() throws IOException {
- // don't log a blank message if the last character was a newline
- if (buf.length() > 0) {
- log();
+ public void write(int c) throws IOException {
+ extractMessages(new char[] { (char) c }, 0, 1);
+ if (writer != null) {
+ writer.write(c);
}
}
@Override
- public void flush() throws IOException {
- // flushing automatically happens when a newline is encountered
+ public void write(char[] cbuf) throws IOException {
+ extractMessages(cbuf, 0, cbuf.length);
+ if (writer != null) {
+ writer.write(cbuf);
+ }
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
- int currOff = off;
- synchronized (buf) {
+ extractMessages(cbuf, off, len);
+ if (writer != null) {
+ writer.write(cbuf, off, len);
+ }
+ }
+
+ @Override
+ public void write(String str) throws IOException {
+ extractMessages(str, 0, str.length());
+ if (writer != null) {
+ writer.write(str);
+ }
+ }
+
+ @Override
+ public void write(String str, int off, int len) throws IOException {
+ extractMessages(str, off, len);
+ if (writer != null) {
+ writer.write(str, off, len);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (writer != null) {
+ writer.flush();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ synchronized (msg) {
+ closed = true;
+ // don't log a blank message if the last character was a newline
+ if (msg.length() > 0) {
+ logMessage();
+ }
+ }
+ if (writer != null) {
+ writer.close();
+ }
+ }
+
+ private void extractMessages(char[] cbuf, int off, int len) {
+ extractMessages(CharBuffer.wrap(cbuf), off, len);
+ }
+
+ private void extractMessages(CharSequence str, int off, int len) {
+ synchronized (msg) {
+ if (closed) {
+ return;
+ }
for (int pos = off; pos < off + len; pos++) {
- switch (cbuf[pos]) {
+ switch (str.charAt(pos)) {
case '\r':
- buf.append(cbuf, currOff, pos - currOff);
- currOff = pos + 1;
+ msg.append(str, off, pos - off);
+ len -= (pos - off);
+ off = pos + 1;
break;
case '\n':
- buf.append(cbuf, currOff, pos - currOff);
- currOff = pos + 1;
- log();
+ msg.append(str, off, pos - off);
+ len -= (pos - off);
+ off = pos + 1;
+ logMessage();
break;
}
}
- buf.append(cbuf, currOff, len - (currOff - off));
+ msg.append(str, off, len);
}
}
- private void log() {
- final Message message = logger.getMessageFactory().newMessage(buf.toString());
- buf.setLength(0);
- logger.log(marker, FQCN, level, message, null);
+ private void logMessage() {
+ logger.log(level, marker, msg.toString());
+ msg.setLength(0);
}
}
Index: log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java (revision 1574084)
+++ log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerContext.java (working copy)
@@ -53,4 +53,6 @@
*/
boolean hasLogger(String name);
+ LoggerExtension extendLogger(String name, Class> extensionClass);
+
}
Index: log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerOutputStream.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerOutputStream.java (revision 0)
+++ log4j-api/src/main/java/org/apache/logging/log4j/spi/LoggerOutputStream.java (revision 0)
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+
+/**
+ * Output stream that logs each line written to a pre-defined level. Can also be configured with a
+ * Marker. This class provides an interface that follows the {@link java.io.PrintStream} methods in
+ * spirit, but doesn't output to any external stream. This class should not be used as a
+ * stream for an underlying logger unless it's being used as a bridge. Otherwise, infinite loops may
+ * occur!
+ */
+public class LoggerOutputStream extends OutputStream {
+ private static final int BUFFER_SIZE = 1024;
+
+ private final OutputStream out;
+ private final AbstractLogger logger;
+ private final Level level;
+ private final Marker marker;
+ private final ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);
+ private final char[] msgBuf = new char[BUFFER_SIZE];
+ private final InputStreamReader msgReader;
+ private final StringBuilder msg = new StringBuilder();
+ private boolean closed;
+
+ public LoggerOutputStream(OutputStream out, Charset charset, AbstractLogger logger, Level level, Marker marker) {
+ this.out = out;
+ this.logger = logger;
+ this.level = level;
+ this.marker = marker;
+ this.msgReader = new InputStreamReader(new ByteBufferInputStream(), charset);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ synchronized (msg) {
+ buf.put((byte) (b & 0xFF));
+ extractMessages();
+ }
+ if (out != null) {
+ out.write(b);
+ }
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ synchronized (msg) {
+ while (len > buf.remaining()) {
+ final int remaining = buf.remaining();
+ buf.put(b, off, remaining);
+ len -= remaining;
+ off += remaining;
+ extractMessages();
+ }
+ buf.put(b, off, len);
+ extractMessages();
+ }
+ if (out != null) {
+ out.write(b, off, len);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (out != null) {
+ out.flush();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ synchronized (msg) {
+ closed = true;
+ // don't log a blank message if the last character was a newline
+ if (msg.length() > 0) {
+ logMessage();
+ }
+ }
+ if (out != null) {
+ out.close();
+ }
+ }
+
+ private void extractMessages() throws IOException {
+ if (closed) {
+ return;
+ }
+ int read = msgReader.read(msgBuf);
+ while (read >= 0) {
+ int off = 0;
+ for (int pos = 0; pos < read; pos++) {
+ switch (msgBuf[pos]) {
+ case '\r':
+ msg.append(msgBuf, off, pos - off);
+ off = pos + 1;
+ break;
+ case '\n':
+ msg.append(msgBuf, off, pos - off);
+ off = pos + 1;
+ logMessage();
+ break;
+ }
+ }
+ msg.append(msgBuf, off, read - off);
+ read = msgReader.read(msgBuf);
+ }
+ }
+
+ private void logMessage() {
+ logger.log(level, marker, msg.toString());
+ }
+
+ private class ByteBufferInputStream extends InputStream {
+
+ public int read() throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+ return buf.get() & 0xFF;
+ }
+
+ public int read(byte[] bytes, int off, int len) throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+
+ len = Math.min(len, buf.remaining());
+ buf.get(bytes, off, len);
+ return len;
+ }
+ }
+}
Index: log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLoggerContext.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLoggerContext.java (revision 1574084)
+++ log4j-api/src/main/java/org/apache/logging/log4j/simple/SimpleLoggerContext.java (working copy)
@@ -27,7 +27,9 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MessageFactory;
import org.apache.logging.log4j.spi.AbstractLogger;
+import org.apache.logging.log4j.spi.ExtensibleLogger;
import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.spi.LoggerExtension;
import org.apache.logging.log4j.util.PropertiesUtil;
/**
@@ -49,8 +51,8 @@
/** Include the instance name in the log message? */
private final boolean showLogName;
/**
- * Include the short name ( last component ) of the logger in the log message. Defaults to true - otherwise we'll be
- * lost in a flood of messages without knowing who sends them.
+ * Include the short name ( last component ) of the logger in the log message. Defaults to true
+ * - otherwise we'll be lost in a flood of messages without knowing who sends them.
*/
private final boolean showShortName;
/** Include the current time in the log message */
@@ -76,8 +78,7 @@
final String lvl = props.getStringProperty(SYSTEM_PREFIX + "level");
defaultLevel = Level.toLevel(lvl, Level.ERROR);
- dateTimeFormat = showDateTime ? props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + "dateTimeFormat",
- DEFAULT_DATE_TIME_FORMAT) : null;
+ dateTimeFormat = showDateTime ? props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + "dateTimeFormat", DEFAULT_DATE_TIME_FORMAT) : null;
final String fileName = props.getStringProperty(SYSTEM_PREFIX + "logFile", "system.err");
PrintStream ps;
@@ -109,8 +110,8 @@
return logger;
}
- loggers.putIfAbsent(name, new SimpleLogger(name, defaultLevel, showLogName, showShortName, showDateTime,
- showContextMap, dateTimeFormat, messageFactory, props, stream));
+ loggers.putIfAbsent(name, new SimpleLogger(name, defaultLevel, showLogName, showShortName, showDateTime, showContextMap, dateTimeFormat,
+ messageFactory, props, stream));
return loggers.get(name);
}
@@ -123,4 +124,9 @@
public Object getExternalContext() {
return null;
}
+
+ @Override
+ public LoggerExtension extendLogger(final String name, final Class> extensionClass) {
+ return ((ExtensibleLogger) getLogger(name)).extend(extensionClass);
+ }
}
Index: log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
===================================================================
--- log4j-api/src/main/java/org/apache/logging/log4j/Logger.java (revision 1574084)
+++ log4j-api/src/main/java/org/apache/logging/log4j/Logger.java (working copy)
@@ -16,8 +16,6 @@
*/
package org.apache.logging.log4j;
-import java.io.PrintWriter;
-
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.MessageFactory;
@@ -465,23 +463,6 @@
String getName();
/**
- * Gets a print stream that logs lines to this logger.
- *
- * @param level the logging level
- * @return print stream that logs printed lines to this logger.
- */
- PrintWriter printWriter(Level level);
-
- /**
- * Gets a marked print stream that logs lines to this logger.
- *
- * @param marker the marker data specific to this log statement
- * @param level the logging level
- * @return print stream that logs printed lines to this logger.
- */
- PrintWriter printWriter(Marker marker, Level level);
-
- /**
* Logs a message with the specific Marker at the {@link Level#INFO INFO} level.
*
* @param marker the marker data specific to this log statement
Index: log4j-jcl/src/main/java/org/apache/logging/log4j/jcl/Log4jLog.java
===================================================================
--- log4j-jcl/src/main/java/org/apache/logging/log4j/jcl/Log4jLog.java (revision 1574084)
+++ log4j-jcl/src/main/java/org/apache/logging/log4j/jcl/Log4jLog.java (working copy)
@@ -17,17 +17,111 @@
package org.apache.logging.log4j.jcl;
import org.apache.commons.logging.Log;
+import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.spi.AbstractLoggerWrapper;
+import org.apache.logging.log4j.spi.LoggerExtension;
/**
*
*/
-public class Log4jLog extends AbstractLoggerWrapper implements Log {
+public class Log4jLog implements Log {
private static final long serialVersionUID = 1L;
- public Log4jLog(final AbstractLogger logger, final String name) {
- super(logger, name, null);
+ private final LoggerExtension logger;
+
+ public Log4jLog(final LoggerExtension logger) {
+ this.logger = logger;
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return logger.isEnabled(Level.DEBUG, null, null);
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return logger.isEnabled(Level.ERROR, null, null);
+ }
+
+ @Override
+ public boolean isFatalEnabled() {
+ return logger.isEnabled(Level.FATAL, null, null);
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return logger.isEnabled(Level.INFO, null, null);
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return logger.isEnabled(Level.TRACE, null, null);
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return logger.isEnabled(Level.WARN, null, null);
+ }
+
+ @Override
+ public void trace(Object message) {
+ logger.log(Level.TRACE, null, message, null);
+ }
+
+ @Override
+ public void trace(Object message, Throwable t) {
+ logger.log(Level.TRACE, null, message, t);
+ }
+
+ @Override
+ public void debug(Object message) {
+ logger.log(Level.DEBUG, null, message, null);
+ }
+
+ @Override
+ public void debug(Object message, Throwable t) {
+ logger.log(Level.DEBUG, null, message, t);
+ }
+
+ @Override
+ public void info(Object message) {
+ logger.log(Level.INFO, null, message, null);
+ }
+
+ @Override
+ public void info(Object message, Throwable t) {
+ logger.log(Level.INFO, null, message, t);
+ }
+
+ @Override
+ public void warn(Object message) {
+ logger.log(Level.WARN, null, message, null);
+ }
+
+ @Override
+ public void warn(Object message, Throwable t) {
+ logger.log(Level.WARN, null, message, t);
+ }
+
+ @Override
+ public void error(Object message) {
+ logger.log(Level.ERROR, null, message, null);
+ }
+
+ @Override
+ public void error(Object message, Throwable t) {
+ logger.log(Level.ERROR, null, message, t);
+ }
+
+ @Override
+ public void fatal(Object message) {
+ logger.log(Level.FATAL, null, message, null);
+ }
+
+ @Override
+ public void fatal(Object message, Throwable t) {
+ logger.log(Level.FATAL, null, message, t);
}
}
Index: log4j-jcl/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java
===================================================================
--- log4j-jcl/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java (revision 1574084)
+++ log4j-jcl/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java (working copy)
@@ -26,15 +26,16 @@
import org.apache.commons.logging.LogFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.spi.AbstractLogger;
+import org.apache.logging.log4j.spi.ExtensibleLogger;
import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.spi.LoggerExtension;
/**
*
*/
public class LogFactoryImpl extends LogFactory {
- private final Map> contextMap =
- new WeakHashMap>();
+ private final Map> contextMap = new WeakHashMap>();
private final ConcurrentMap attributes = new ConcurrentHashMap();
@@ -44,13 +45,9 @@
if (loggers.containsKey(name)) {
return loggers.get(name);
}
- final org.apache.logging.log4j.Logger logger = PrivateManager.getLogger(name);
- if (logger instanceof AbstractLogger) {
- loggers.putIfAbsent(name, new Log4jLog((AbstractLogger) logger, name));
- return loggers.get(name);
- }
- throw new LogConfigurationException(
- "Commons Logging Adapter requires base logging system to extend Log4j AbstractLogger");
+ LoggerExtension logger = PrivateManager.getContext().extendLogger(name, Log4jLog.class);
+ loggers.putIfAbsent(name, new Log4jLog(logger));
+ return loggers.get(name);
}
private ConcurrentMap getLoggersMap() {
@@ -81,8 +78,8 @@
}
/**
- * This method is supposed to clear all loggers. In this implementation it will clear all the logger
- * wrappers but the loggers managed by the underlying logger context will not be.
+ * This method is supposed to clear all loggers. In this implementation it will clear all the
+ * logger wrappers but the loggers managed by the underlying logger context will not be.
*/
@Override
public void release() {
Index: log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java
===================================================================
--- log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java (revision 1574084)
+++ log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java (working copy)
@@ -113,27 +113,27 @@
}
@Override
- public boolean isEnabled(final Level level, final Marker marker, final String msg) {
+ protected boolean isEnabled(final Level level, final Marker marker, final String msg) {
return config.filter(level, marker, msg);
}
@Override
- public boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) {
+ protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) {
return config.filter(level, marker, msg, t);
}
@Override
- public boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) {
+ protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) {
return config.filter(level, marker, msg, p1);
}
@Override
- public boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) {
+ protected boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) {
return config.filter(level, marker, msg, t);
}
@Override
- public boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) {
+ protected boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) {
return config.filter(level, marker, msg, t);
}
Index: log4j-slf4j-impl/src/main/java/org/slf4j/helpers/Log4jLoggerFactory.java
===================================================================
--- log4j-slf4j-impl/src/main/java/org/slf4j/helpers/Log4jLoggerFactory.java (revision 1574084)
+++ log4j-slf4j-impl/src/main/java/org/slf4j/helpers/Log4jLoggerFactory.java (working copy)
@@ -24,6 +24,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.logging.log4j.spi.LoggerExtension;
import org.apache.logging.slf4j.SLF4JLoggingException;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
@@ -50,12 +51,9 @@
return loggers.get(name);
}
final String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name;
- final org.apache.logging.log4j.Logger logger = context.getLogger(key);
- if (logger instanceof AbstractLogger) {
- loggers.putIfAbsent(name, new SLF4JLogger((AbstractLogger) logger, name));
- return loggers.get(name);
- }
- throw new SLF4JLoggingException("SLF4J Adapter requires base logging system to extend Log4j AbstractLogger");
+ final LoggerExtension logger = context.extendLogger(name, Log4jLoggerFactory.class);
+ loggers.putIfAbsent(name, new SLF4JLogger(logger, name));
+ return loggers.get(name);
}
private ConcurrentMap getLoggersMap(final LoggerContext context) {
Index: log4j-slf4j-impl/src/main/java/org/slf4j/impl/SLF4JLogger.java
===================================================================
--- log4j-slf4j-impl/src/main/java/org/slf4j/impl/SLF4JLogger.java (revision 1574084)
+++ log4j-slf4j-impl/src/main/java/org/slf4j/impl/SLF4JLogger.java (working copy)
@@ -23,6 +23,7 @@
import org.apache.logging.log4j.message.SimpleMessage;
import org.apache.logging.log4j.spi.AbstractLogger;
import org.apache.logging.log4j.spi.AbstractLoggerWrapper;
+import org.apache.logging.log4j.spi.LoggerExtension;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.slf4j.helpers.EventDataConverter;
@@ -39,15 +40,14 @@
public class SLF4JLogger implements LocationAwareLogger, Serializable {
private static final long serialVersionUID = 7869000638091304316L;
- private static final String FQCN = SLF4JLogger.class.getName();
private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
private final boolean eventLogger;
- private transient AbstractLoggerWrapper logger;
+ private transient LoggerExtension logger;
private final String name;
private transient EventDataConverter converter;
- public SLF4JLogger(final AbstractLogger logger, final String name) {
- this.logger = new AbstractLoggerWrapper(logger, name, null);
+ public SLF4JLogger(final LoggerExtension logger, final String name) {
+ this.logger = logger;
this.eventLogger = "EventLogger".equals(name);
this.name = name;
this.converter = createConverter();
@@ -55,88 +55,62 @@
@Override
public void trace(final String format) {
- if (logger.isTraceEnabled()) {
- logger.log(null, FQCN, Level.TRACE, new SimpleMessage(format), null);
- }
+ logger.log(Level.TRACE, null, format);
}
@Override
public void trace(final String format, final Object o) {
- if (logger.isTraceEnabled()) {
- logger.log(null, FQCN, Level.TRACE, new ParameterizedMessage(format, o), null);
- }
+ logger.log(Level.TRACE, null, format, o);
}
@Override
public void trace(final String format, final Object arg1, final Object arg2) {
- if (logger.isTraceEnabled()) {
- final ParameterizedMessage msg = new ParameterizedMessage(format, arg1, arg2);
- logger.log(null, FQCN, Level.TRACE, msg, msg.getThrowable());
- }
+ logger.log(Level.TRACE, null, format, arg1, arg2);
}
@Override
public void trace(final String format, final Object... args) {
- if (logger.isTraceEnabled()) {
- final ParameterizedMessage msg = new ParameterizedMessage(format, args);
- logger.log(null, FQCN, Level.TRACE, msg, msg.getThrowable());
- }
+ logger.log(Level.TRACE, null, format, args);
}
@Override
public void trace(final String format, final Throwable t) {
- if (logger.isTraceEnabled()) {
- logger.log(null, FQCN, Level.TRACE, new SimpleMessage(format), t);
- }
+ logger.log(Level.TRACE, null, format, t);
}
@Override
public boolean isTraceEnabled() {
- return logger.isTraceEnabled();
+ return logger.isEnabled(Level.TRACE, null, null);
}
@Override
public boolean isTraceEnabled(final Marker marker) {
- return logger.isTraceEnabled((org.apache.logging.log4j.Marker) marker);
+ return logger.isEnabled(Level.TRACE, (org.apache.logging.log4j.Marker) marker, null);
}
@Override
public void trace(final Marker marker, final String s) {
- if (isTraceEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.TRACE, new SimpleMessage(s), null);
- }
+ logger.log(Level.TRACE, (org.apache.logging.log4j.Marker) marker, s);
}
@Override
public void trace(final Marker marker, final String s, final Object o) {
- if (isTraceEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.TRACE,
- new ParameterizedMessage(s, o), null);
- }
+ logger.log(Level.TRACE, (org.apache.logging.log4j.Marker) marker, s, o);
}
@Override
public void trace(final Marker marker, final String s, final Object o, final Object o1) {
- if (isTraceEnabled(marker)) {
- final ParameterizedMessage msg = new ParameterizedMessage(s, o, o1);
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.TRACE, msg, msg.getThrowable());
- }
+ logger.log(Level.TRACE, (org.apache.logging.log4j.Marker) marker, s, o, o1);
}
@Override
public void trace(final Marker marker, final String s, final Object... objects) {
- if (isTraceEnabled(marker)) {
- final ParameterizedMessage msg = new ParameterizedMessage(s, objects);
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.TRACE, msg, msg.getThrowable());
- }
+ logger.log(Level.TRACE, (org.apache.logging.log4j.Marker) marker, s, objects);
}
@Override
public void trace(final Marker marker, final String s, final Throwable throwable) {
- if (isTraceEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.TRACE,
- new SimpleMessage(s), throwable);
- }
+ logger.log(Level.TRACE, (org.apache.logging.log4j.Marker) marker, s, throwable);
}
@Override
@@ -196,8 +170,7 @@
@Override
public void debug(final Marker marker, final String s, final Object o) {
if (isDebugEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.DEBUG,
- new ParameterizedMessage(s, o), null);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.DEBUG, new ParameterizedMessage(s, o), null);
}
}
@@ -220,8 +193,7 @@
@Override
public void debug(final Marker marker, final String s, final Throwable throwable) {
if (isDebugEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.DEBUG,
- new SimpleMessage(s), throwable);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.DEBUG, new SimpleMessage(s), throwable);
}
}
@@ -282,8 +254,7 @@
@Override
public void info(final Marker marker, final String s, final Object o) {
if (isInfoEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.INFO,
- new ParameterizedMessage(s, o), null);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.INFO, new ParameterizedMessage(s, o), null);
}
}
@@ -306,8 +277,7 @@
@Override
public void info(final Marker marker, final String s, final Throwable throwable) {
if (isInfoEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.INFO,
- new SimpleMessage(s), throwable);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.INFO, new SimpleMessage(s), throwable);
}
}
@@ -368,8 +338,7 @@
@Override
public void warn(final Marker marker, final String s, final Object o) {
if (isWarnEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.WARN,
- new ParameterizedMessage(s, o), null);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.WARN, new ParameterizedMessage(s, o), null);
}
}
@@ -392,8 +361,7 @@
@Override
public void warn(final Marker marker, final String s, final Throwable throwable) {
if (isWarnEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.WARN,
- new SimpleMessage(s), throwable);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.WARN, new SimpleMessage(s), throwable);
}
}
@@ -454,8 +422,7 @@
@Override
public void error(final Marker marker, final String s, final Object o) {
if (isErrorEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.ERROR,
- new ParameterizedMessage(s, o), null);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.ERROR, new ParameterizedMessage(s, o), null);
}
}
@@ -478,22 +445,19 @@
@Override
public void error(final Marker marker, final String s, final Throwable throwable) {
if (isErrorEnabled(marker)) {
- logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.ERROR,
- new SimpleMessage(s), throwable);
+ logger.log((org.apache.logging.log4j.Marker) marker, FQCN, Level.ERROR, new SimpleMessage(s), throwable);
}
}
-
@Override
- public void log(final Marker marker, final String fqcn, final int i, final String s1, final Object[] objects,
- Throwable throwable) {
+ public void log(final Marker marker, final String fqcn, final int i, final String s1, final Object[] objects, Throwable throwable) {
if (!logger.isEnabled(getLevel(i), (org.apache.logging.log4j.Marker) marker, s1)) {
return;
}
Message msg;
if (eventLogger && marker != null && marker.contains(EVENT_MARKER) && converter != null) {
msg = converter.convertEvent(s1, objects, throwable);
- } else if (objects == null) {
+ } else if (objects == null) {
msg = new SimpleMessage(s1);
} else {
msg = new ParameterizedMessage(s1, objects, throwable);
@@ -510,23 +474,21 @@
}
/**
- * Always treat de-serialization as a full-blown constructor, by
- * validating the final state of the de-serialized object.
+ * Always treat de-serialization as a full-blown constructor, by validating the final state of
+ * the de-serialized object.
*/
private void readObject(ObjectInputStream aInputStream) throws ClassNotFoundException, IOException {
- //always perform the default de-serialization first
+ // always perform the default de-serialization first
aInputStream.defaultReadObject();
logger = new AbstractLoggerWrapper((AbstractLogger) LogManager.getLogger(name), name, null);
converter = createConverter();
}
/**
- * This is the default implementation of writeObject.
- * Customise if necessary.
+ * This is the default implementation of writeObject. Customise if necessary.
*/
- private void writeObject(ObjectOutputStream aOutputStream
- ) throws IOException {
- //perform the default serialization for all non-transient, non-static fields
+ private void writeObject(ObjectOutputStream aOutputStream) throws IOException {
+ // perform the default serialization for all non-transient, non-static fields
aOutputStream.defaultWriteObject();
}
@@ -541,16 +503,16 @@
private Level getLevel(final int i) {
switch (i) {
- case TRACE_INT :
- return Level.TRACE;
- case DEBUG_INT :
- return Level.DEBUG;
- case INFO_INT :
- return Level.INFO;
- case WARN_INT :
- return Level.WARN;
- case ERROR_INT :
- return Level.ERROR;
+ case TRACE_INT:
+ return Level.TRACE;
+ case DEBUG_INT:
+ return Level.DEBUG;
+ case INFO_INT:
+ return Level.INFO;
+ case WARN_INT:
+ return Level.WARN;
+ case ERROR_INT:
+ return Level.ERROR;
}
return Level.ERROR;
}