LOG4J2-2305 - Create separate implementation for SLF4J 1.8
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/0ebbd84d Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/0ebbd84d Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/0ebbd84d Branch: refs/heads/release-2.x Commit: 0ebbd84d2f2b4e78abb179b9f8313b9cab26fae1 Parents: 922fefd Author: Ralph Goers <[email protected]> Authored: Thu Jul 5 22:24:03 2018 -0700 Committer: Ralph Goers <[email protected]> Committed: Thu Jul 5 22:24:03 2018 -0700 ---------------------------------------------------------------------- log4j-slf4j-impl/pom.xml | 40 -- log4j-slf4j-impl/src/assembly/slf4j.xml | 39 -- log4j-slf4j18-impl/pom.xml | 41 -- .../logging/slf4j/EventDataConverter.java | 50 +++ .../org/apache/logging/slf4j/Log4jLogger.java | 439 +++++++++++++++++++ .../logging/slf4j/Log4jLoggerFactory.java | 58 +++ .../apache/logging/slf4j/Log4jMDCAdapter.java | 62 +++ .../org/apache/logging/slf4j/Log4jMarker.java | 132 ++++++ .../logging/slf4j/Log4jMarkerFactory.java | 138 ++++++ .../logging/slf4j/SLF4JLoggingException.java | 41 ++ .../logging/slf4j/SLF4JServiceProvider.java | 6 +- .../org/apache/logging/slf4j/package-info.java | 22 + .../apache/logging/slf4j/Log4jMarkerTest.java | 15 +- .../org/apache/logging/slf4j/MarkerTest.java | 26 +- 14 files changed, 975 insertions(+), 134 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j-impl/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-slf4j-impl/pom.xml b/log4j-slf4j-impl/pom.xml index a34a16d..9614201 100644 --- a/log4j-slf4j-impl/pom.xml +++ b/log4j-slf4j-impl/pom.xml @@ -161,46 +161,6 @@ </instructions> </configuration> </plugin> - <plugin> - <artifactId>maven-assembly-plugin</artifactId> - <executions> - <execution> - <id>zip</id> - <phase>package</phase> - <goals> - <goal>single</goal> - </goals> - <configuration> - <finalName>log4j-slf4j-impl-${project.version}</finalName> - <attach>false</attach> - <appendAssemblyId>false</appendAssemblyId> - <descriptors> - <descriptor>src/assembly/slf4j.xml</descriptor> - </descriptors> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-install-plugin</artifactId> - <executions> - <execution> - <id>zip</id> - <phase>install</phase> - <goals> - <goal>install-file</goal> - </goals> - <configuration> - <groupId>${project.groupId}</groupId> - <artifactId>${project.artifactId}</artifactId> - <version>${project.version}</version> - <packaging>zip</packaging> - <file>${project.build.directory}/${project.build.finalName}.zip</file> - </configuration> - </execution> - </executions> - </plugin> </plugins> </build> <reporting> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j-impl/src/assembly/slf4j.xml ---------------------------------------------------------------------- diff --git a/log4j-slf4j-impl/src/assembly/slf4j.xml b/log4j-slf4j-impl/src/assembly/slf4j.xml deleted file mode 100644 index 6542d5e..0000000 --- a/log4j-slf4j-impl/src/assembly/slf4j.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<!-- - 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. ---> - -<assembly> - <id>src</id> - <formats> - <format>zip</format> - </formats> - <baseDirectory>/</baseDirectory> - <fileSets> - <fileSet> - <directory>${project.build.outputDirectory}</directory> - <outputDirectory>/classes</outputDirectory> - <includes> - <include>**/*.class</include> - </includes> - <excludes> - <exclude>org/slf4j/impl/*.class</exclude> - </excludes> - </fileSet> - </fileSets> -</assembly> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/pom.xml b/log4j-slf4j18-impl/pom.xml index f1fb21e..6e10af3 100644 --- a/log4j-slf4j18-impl/pom.xml +++ b/log4j-slf4j18-impl/pom.xml @@ -57,17 +57,6 @@ </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - <scope>provided</scope> - <type>zip</type> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <type>test-jar</type> <scope>test</scope> @@ -96,36 +85,6 @@ </dependencies> <build> <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <version>3.0.2</version> - <executions> - <execution> - <id>unpack-classes</id> - <phase>process-resources</phase> - <goals> - <goal>unpack</goal> - </goals> - <configuration> - <artifactItems> - <artifactItem> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - <version>${project.version}</version> - <type>zip</type> - <overWrite>false</overWrite> - </artifactItem> - </artifactItems> - <includes>**/*.class</includes> - <excludes>**/*.java</excludes> - <outputDirectory>${project.build.directory}</outputDirectory> - <overWriteReleases>false</overWriteReleases> - <overWriteSnapshots>true</overWriteSnapshots> - </configuration> - </execution> - </executions> - </plugin> <!-- Include the standard NOTICE and LICENSE --> <plugin> <groupId>org.apache.maven.plugins</groupId> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/EventDataConverter.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/EventDataConverter.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/EventDataConverter.java new file mode 100644 index 0000000..620232a --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/EventDataConverter.java @@ -0,0 +1,50 @@ +/* + * 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.slf4j; + +import java.util.Map; + +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.apache.logging.log4j.message.StructuredDataMessage; +import org.slf4j.ext.EventData; + +/** + * + */ +public class EventDataConverter { + + public Message convertEvent(final String message, final Object[] objects, final Throwable throwable) { + try { + final EventData data = objects != null && objects[0] instanceof EventData ? + (EventData) objects[0] : new EventData(message); + final StructuredDataMessage msg = + new StructuredDataMessage(data.getEventId(), data.getMessage(), data.getEventType()); + for (final Map.Entry<String, Object> entry : data.getEventMap().entrySet()) { + final String key = entry.getKey(); + if (EventData.EVENT_TYPE.equals(key) || EventData.EVENT_ID.equals(key) + || EventData.EVENT_MESSAGE.equals(key)) { + continue; + } + msg.put(key, String.valueOf(entry.getValue())); + } + return msg; + } catch (final Exception ex) { + return new ParameterizedMessage(message, objects, throwable); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java new file mode 100644 index 0000000..6cbb7c4 --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLogger.java @@ -0,0 +1,439 @@ +/* + * 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.slf4j; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.apache.logging.log4j.message.SimpleMessage; +import org.apache.logging.log4j.spi.ExtendedLogger; +import org.apache.logging.log4j.util.LoaderUtil; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; +import org.slf4j.spi.LocationAwareLogger; + +/** + * SLF4J logger implementation that uses Log4j. + */ +public class Log4jLogger implements LocationAwareLogger, Serializable { + + public static final String FQCN = Log4jLogger.class.getName(); + + private static final long serialVersionUID = 7869000638091304316L; + private static final Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT"); + private final boolean eventLogger; + private transient ExtendedLogger logger; + private final String name; + private transient EventDataConverter converter; + private transient Log4jMarkerFactory markerFactory; + + public Log4jLogger(final Log4jMarkerFactory markerFactory, final ExtendedLogger logger, final String name) { + this.markerFactory = markerFactory; + this.logger = logger; + this.eventLogger = "EventLogger".equals(name); + this.name = name; + this.converter = createConverter(); + } + + @Override + public void trace(final String format) { + logger.logIfEnabled(FQCN, Level.TRACE, null, format); + } + + @Override + public void trace(final String format, final Object o) { + logger.logIfEnabled(FQCN, Level.TRACE, null, format, o); + } + + @Override + public void trace(final String format, final Object arg1, final Object arg2) { + logger.logIfEnabled(FQCN, Level.TRACE, null, format, arg1, arg2); + } + + @Override + public void trace(final String format, final Object... args) { + logger.logIfEnabled(FQCN, Level.TRACE, null, format, args); + } + + @Override + public void trace(final String format, final Throwable t) { + logger.logIfEnabled(FQCN, Level.TRACE, null, format, t); + } + + @Override + public boolean isTraceEnabled() { + return logger.isEnabled(Level.TRACE, null, null); + } + + @Override + public boolean isTraceEnabled(final Marker marker) { + return logger.isEnabled(Level.TRACE, getMarker(marker), null); + } + + @Override + public void trace(final Marker marker, final String s) { + logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s); + } + + @Override + public void trace(final Marker marker, final String s, final Object o) { + logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o); + } + + @Override + public void trace(final Marker marker, final String s, final Object o, final Object o1) { + logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, o, o1); + } + + @Override + public void trace(final Marker marker, final String s, final Object... objects) { + logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, objects); + } + + @Override + public void trace(final Marker marker, final String s, final Throwable throwable) { + logger.logIfEnabled(FQCN, Level.TRACE, getMarker(marker), s, throwable); + } + + @Override + public void debug(final String format) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, format); + } + + @Override + public void debug(final String format, final Object o) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, format, o); + } + + @Override + public void debug(final String format, final Object arg1, final Object arg2) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, format, arg1, arg2); + } + + @Override + public void debug(final String format, final Object... args) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, format, args); + } + + @Override + public void debug(final String format, final Throwable t) { + logger.logIfEnabled(FQCN, Level.DEBUG, null, format, t); + } + + @Override + public boolean isDebugEnabled() { + return logger.isEnabled(Level.DEBUG, null, null); + } + + @Override + public boolean isDebugEnabled(final Marker marker) { + return logger.isEnabled(Level.DEBUG, getMarker(marker), null); + } + + @Override + public void debug(final Marker marker, final String s) { + logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s); + } + + @Override + public void debug(final Marker marker, final String s, final Object o) { + logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o); + } + + @Override + public void debug(final Marker marker, final String s, final Object o, final Object o1) { + logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, o, o1); + } + + @Override + public void debug(final Marker marker, final String s, final Object... objects) { + logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, objects); + } + + @Override + public void debug(final Marker marker, final String s, final Throwable throwable) { + logger.logIfEnabled(FQCN, Level.DEBUG, getMarker(marker), s, throwable); + } + + @Override + public void info(final String format) { + logger.logIfEnabled(FQCN, Level.INFO, null, format); + } + + @Override + public void info(final String format, final Object o) { + logger.logIfEnabled(FQCN, Level.INFO, null, format, o); + } + + @Override + public void info(final String format, final Object arg1, final Object arg2) { + logger.logIfEnabled(FQCN, Level.INFO, null, format, arg1, arg2); + } + + @Override + public void info(final String format, final Object... args) { + logger.logIfEnabled(FQCN, Level.INFO, null, format, args); + } + + @Override + public void info(final String format, final Throwable t) { + logger.logIfEnabled(FQCN, Level.INFO, null, format, t); + } + + @Override + public boolean isInfoEnabled() { + return logger.isEnabled(Level.INFO, null, null); + } + + @Override + public boolean isInfoEnabled(final Marker marker) { + return logger.isEnabled(Level.INFO, getMarker(marker), null); + } + + @Override + public void info(final Marker marker, final String s) { + logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s); + } + + @Override + public void info(final Marker marker, final String s, final Object o) { + logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o); + } + + @Override + public void info(final Marker marker, final String s, final Object o, final Object o1) { + logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, o, o1); + } + + @Override + public void info(final Marker marker, final String s, final Object... objects) { + logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, objects); + } + + @Override + public void info(final Marker marker, final String s, final Throwable throwable) { + logger.logIfEnabled(FQCN, Level.INFO, getMarker(marker), s, throwable); + } + + @Override + public void warn(final String format) { + logger.logIfEnabled(FQCN, Level.WARN, null, format); + } + + @Override + public void warn(final String format, final Object o) { + logger.logIfEnabled(FQCN, Level.WARN, null, format, o); + } + + @Override + public void warn(final String format, final Object arg1, final Object arg2) { + logger.logIfEnabled(FQCN, Level.WARN, null, format, arg1, arg2); + } + + @Override + public void warn(final String format, final Object... args) { + logger.logIfEnabled(FQCN, Level.WARN, null, format, args); + } + + @Override + public void warn(final String format, final Throwable t) { + logger.logIfEnabled(FQCN, Level.WARN, null, format, t); + } + + @Override + public boolean isWarnEnabled() { + return logger.isEnabled(Level.WARN, null, null); + } + + @Override + public boolean isWarnEnabled(final Marker marker) { + return logger.isEnabled(Level.WARN, getMarker(marker), null); + } + + @Override + public void warn(final Marker marker, final String s) { + logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s); + } + + @Override + public void warn(final Marker marker, final String s, final Object o) { + logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o); + } + + @Override + public void warn(final Marker marker, final String s, final Object o, final Object o1) { + logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, o, o1); + } + + @Override + public void warn(final Marker marker, final String s, final Object... objects) { + logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, objects); + } + + @Override + public void warn(final Marker marker, final String s, final Throwable throwable) { + logger.logIfEnabled(FQCN, Level.WARN, getMarker(marker), s, throwable); + } + + @Override + public void error(final String format) { + logger.logIfEnabled(FQCN, Level.ERROR, null, format); + } + + @Override + public void error(final String format, final Object o) { + logger.logIfEnabled(FQCN, Level.ERROR, null, format, o); + } + + @Override + public void error(final String format, final Object arg1, final Object arg2) { + logger.logIfEnabled(FQCN, Level.ERROR, null, format, arg1, arg2); + } + + @Override + public void error(final String format, final Object... args) { + logger.logIfEnabled(FQCN, Level.ERROR, null, format, args); + } + + @Override + public void error(final String format, final Throwable t) { + logger.logIfEnabled(FQCN, Level.ERROR, null, format, t); + } + + @Override + public boolean isErrorEnabled() { + return logger.isEnabled(Level.ERROR, null, null); + } + + @Override + public boolean isErrorEnabled(final Marker marker) { + return logger.isEnabled(Level.ERROR, getMarker(marker), null); + } + + @Override + public void error(final Marker marker, final String s) { + logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s); + } + + @Override + public void error(final Marker marker, final String s, final Object o) { + logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o); + } + + @Override + public void error(final Marker marker, final String s, final Object o, final Object o1) { + logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, o, o1); + } + + @Override + public void error(final Marker marker, final String s, final Object... objects) { + logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, objects); + } + + @Override + public void error(final Marker marker, final String s, final Throwable throwable) { + logger.logIfEnabled(FQCN, Level.ERROR, getMarker(marker), s, throwable); + } + + @Override + public void log(final Marker marker, final String fqcn, final int level, final String message, final Object[] params, Throwable throwable) { + final Level log4jLevel = getLevel(level); + final org.apache.logging.log4j.Marker log4jMarker = getMarker(marker); + + if (!logger.isEnabled(log4jLevel, log4jMarker, message, params)) { + return; + } + final Message msg; + if (eventLogger && marker != null && marker.contains(EVENT_MARKER) && converter != null) { + msg = converter.convertEvent(message, params, throwable); + } else if (params == null) { + msg = new SimpleMessage(message); + } else { + msg = new ParameterizedMessage(message, params, throwable); + if (throwable != null) { + throwable = msg.getThrowable(); + } + } + logger.logMessage(fqcn, log4jLevel, log4jMarker, msg, throwable); + } + + private org.apache.logging.log4j.Marker getMarker(final Marker marker) { + if (marker == null) { + return null; + } else if (marker instanceof Log4jMarker) { + return ((Log4jMarker) marker).getLog4jMarker(); + } else { + return ((Log4jMarker) markerFactory.getMarker(marker)).getLog4jMarker(); + } + } + + @Override + public String getName() { + return name; + } + + /** + * Always treat de-serialization as a full-blown constructor, by validating the final state of + * the de-serialized object. + */ + private void readObject(final ObjectInputStream aInputStream) throws ClassNotFoundException, IOException { + // always perform the default de-serialization first + aInputStream.defaultReadObject(); + logger = LogManager.getContext().getLogger(name); + converter = createConverter(); + markerFactory = ((Log4jLoggerFactory) org.slf4j.LoggerFactory.getILoggerFactory()).getMarkerFactory(); + } + + /** + * This is the default implementation of writeObject. Customise if necessary. + */ + private void writeObject(final ObjectOutputStream aOutputStream) throws IOException { + // perform the default serialization for all non-transient, non-static fields + aOutputStream.defaultWriteObject(); + } + + private static EventDataConverter createConverter() { + try { + LoaderUtil.loadClass("org.slf4j.ext.EventData"); + return new EventDataConverter(); + } catch (final ClassNotFoundException cnfe) { + return null; + } + } + + private static 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; + } + return Level.ERROR; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLoggerFactory.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLoggerFactory.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLoggerFactory.java new file mode 100644 index 0000000..fcf1d66 --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jLoggerFactory.java @@ -0,0 +1,58 @@ +/* + * 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.slf4j; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.spi.AbstractLoggerAdapter; +import org.apache.logging.log4j.spi.LoggerContext; +import org.apache.logging.log4j.util.StackLocatorUtil; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; + +/** + * Log4j implementation of SLF4J ILoggerFactory interface. + */ +public class Log4jLoggerFactory extends AbstractLoggerAdapter<Logger> implements ILoggerFactory { + + private static final String FQCN = Log4jLoggerFactory.class.getName(); + private static final String PACKAGE = "org.slf4j"; + private final Log4jMarkerFactory markerFactory; + + public Log4jLoggerFactory(Log4jMarkerFactory markerFactory) { + this.markerFactory = markerFactory; + } + + + @Override + protected Logger newLogger(final String name, final LoggerContext context) { + final String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name; + return new Log4jLogger(markerFactory, context.getLogger(key), name); + } + + @Override + protected LoggerContext getContext() { + final Class<?> anchor = StackLocatorUtil.getCallerClass(FQCN, PACKAGE); + return anchor == null ? LogManager.getContext() : getContext(StackLocatorUtil.getCallerClass(anchor)); + } + + + Log4jMarkerFactory getMarkerFactory() { + return markerFactory; + } + + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMDCAdapter.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMDCAdapter.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMDCAdapter.java new file mode 100644 index 0000000..ba32dc6 --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMDCAdapter.java @@ -0,0 +1,62 @@ +/* + * 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.slf4j; + +import java.util.Map; + +import org.apache.logging.log4j.ThreadContext; +import org.slf4j.spi.MDCAdapter; + +/** + * + */ +public class Log4jMDCAdapter implements MDCAdapter { + + @Override + public void put(final String key, final String val) { + ThreadContext.put(key, val); + } + + @Override + public String get(final String key) { + return ThreadContext.get(key); + } + + @Override + public void remove(final String key) { + ThreadContext.remove(key); + } + + @Override + public void clear() { + ThreadContext.clearMap(); + } + + @Override + public Map<String, String> getCopyOfContextMap() { + return ThreadContext.getContext(); + } + + @Override + @SuppressWarnings("unchecked") // nothing we can do about this, restricted by SLF4J API + public void setContextMap(@SuppressWarnings("rawtypes") final Map map) { + ThreadContext.clearMap(); + for (final Map.Entry<String, String> entry : ((Map<String, String>) map).entrySet()) { + ThreadContext.put(entry.getKey(), entry.getValue()); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarker.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarker.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarker.java new file mode 100644 index 0000000..00351f9 --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarker.java @@ -0,0 +1,132 @@ +/* + * 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.slf4j; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.logging.log4j.MarkerManager; +import org.slf4j.IMarkerFactory; +import org.slf4j.Marker; + +/** + * Log4j/SLF4J {@link Marker} type bridge. + */ +class Log4jMarker implements Marker { + + public static final long serialVersionUID = 1590472L; + + private final IMarkerFactory factory; + + private final org.apache.logging.log4j.Marker marker; + + /** + * Constructs a Log4jMarker using an existing Log4j {@link org.apache.logging.log4j.Marker}. + * @param marker The Log4j Marker upon which to base this Marker. + */ + public Log4jMarker(final IMarkerFactory markerFactory, final org.apache.logging.log4j.Marker marker) { + this.factory = markerFactory; + this.marker = marker; + } + + @Override + public void add(final Marker marker) { + if (marker == null) { + throw new IllegalArgumentException(); + } + final Marker m = factory.getMarker(marker.getName()); + this.marker.addParents(((Log4jMarker)m).getLog4jMarker()); + } + + @Override + public boolean contains(final Marker marker) { + if (marker == null) { + throw new IllegalArgumentException(); + } + return this.marker.isInstanceOf(marker.getName()); + } + + @Override + public boolean contains(final String s) { + return s != null ? this.marker.isInstanceOf(s) : false; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Log4jMarker)) { + return false; + } + final Log4jMarker other = (Log4jMarker) obj; + if (marker == null) { + if (other.marker != null) { + return false; + } + } else if (!marker.equals(other.marker)) { + return false; + } + return true; + } + + public org.apache.logging.log4j.Marker getLog4jMarker() { + return marker; + } + + @Override + public String getName() { + return marker.getName(); + } + + @Override + public boolean hasChildren() { + return marker.hasParents(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((marker == null) ? 0 : marker.hashCode()); + return result; + } + + @Override + public boolean hasReferences() { + return marker.hasParents(); + } + + @Override + public Iterator<Marker> iterator() { + final org.apache.logging.log4j.Marker[] log4jParents = this.marker.getParents(); + final List<Marker> parents = new ArrayList<>(log4jParents.length); + for (final org.apache.logging.log4j.Marker m : log4jParents) { + parents.add(factory.getMarker(m.getName())); + } + return parents.iterator(); + } + + @Override + public boolean remove(final Marker marker) { + return marker != null ? this.marker.remove(MarkerManager.getMarker(marker.getName())) : false; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java new file mode 100644 index 0000000..69ea94b --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/Log4jMarkerFactory.java @@ -0,0 +1,138 @@ +/* + * 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.slf4j; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.MarkerManager; +import org.apache.logging.log4j.status.StatusLogger; +import org.slf4j.IMarkerFactory; +import org.slf4j.Marker; + +/** + * Log4j/SLF4J bridge to create SLF4J Markers based on name or based on existing SLF4J Markers. + */ +public class Log4jMarkerFactory implements IMarkerFactory { + + private static final Logger LOGGER = StatusLogger.getLogger(); + + private final ConcurrentMap<String, Marker> markerMap = new ConcurrentHashMap<>(); + + /** + * Returns a Log4j Marker that is compatible with SLF4J. + * @param name The name of the Marker. + * @return A Marker. + */ + @Override + public Marker getMarker(final String name) { + if (name == null) { + throw new IllegalArgumentException("Marker name must not be null"); + } + final Marker marker = markerMap.get(name); + if (marker != null) { + return marker; + } + final org.apache.logging.log4j.Marker log4jMarker = MarkerManager.getMarker(name); + return addMarkerIfAbsent(name, log4jMarker); + } + + private Marker addMarkerIfAbsent(final String name, final org.apache.logging.log4j.Marker log4jMarker) { + final Marker marker = new Log4jMarker(this, log4jMarker); + final Marker existing = markerMap.putIfAbsent(name, marker); + return existing == null ? marker : existing; + } + + /** + * Returns a Log4j Marker converted from an existing custom SLF4J Marker. + * @param marker The SLF4J Marker to convert. + * @return A converted Log4j/SLF4J Marker. + * @since 2.1 + */ + public Marker getMarker(final Marker marker) { + if (marker == null) { + throw new IllegalArgumentException("Marker must not be null"); + } + final Marker m = markerMap.get(marker.getName()); + if (m != null) { + return m; + } + return addMarkerIfAbsent(marker.getName(), convertMarker(marker)); + } + + private static org.apache.logging.log4j.Marker convertMarker(final Marker original) { + if (original == null) { + throw new IllegalArgumentException("Marker must not be null"); + } + return convertMarker(original, new ArrayList<Marker>()); + } + + private static org.apache.logging.log4j.Marker convertMarker(final Marker original, + final Collection<Marker> visited) { + final org.apache.logging.log4j.Marker marker = MarkerManager.getMarker(original.getName()); + if (original.hasReferences()) { + final Iterator<Marker> it = original.iterator(); + while (it.hasNext()) { + final Marker next = it.next(); + if (visited.contains(next)) { + LOGGER.warn("Found a cycle in Marker [{}]. Cycle will be broken.", next.getName()); + } else { + visited.add(next); + marker.addParents(convertMarker(next, visited)); + } + } + } + return marker; + } + + /** + * Returns true if the Marker exists. + * @param name The Marker name. + * @return {@code true} if the Marker exists, {@code false} otherwise. + */ + @Override + public boolean exists(final String name) { + return markerMap.containsKey(name); + } + + /** + * Log4j does not support detached Markers. This method always returns false. + * @param name The Marker name. + * @return {@code false} + */ + @Override + public boolean detachMarker(final String name) { + return false; + } + + /** + * Log4j does not support detached Markers for performance reasons. The returned Marker is attached. + * @param name The Marker name. + * @return The named Marker (unmodified). + */ + @Override + public Marker getDetachedMarker(final String name) { + LOGGER.warn("Log4j does not support detached Markers. Returned Marker [{}] will be unchanged.", name); + return getMarker(name); + } + + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JLoggingException.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JLoggingException.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JLoggingException.java new file mode 100644 index 0000000..0a41215 --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JLoggingException.java @@ -0,0 +1,41 @@ +/* + * 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.slf4j; + +/** + * Exception thrown when the SLF4J adapter encounters a problem. + * + */ +public class SLF4JLoggingException extends RuntimeException { + + /** + * Generated serial version ID. + */ + private static final long serialVersionUID = -1618650972455089998L; + + public SLF4JLoggingException(final String msg) { + super(msg); + } + + public SLF4JLoggingException(final String msg, final Exception ex) { + super(msg, ex); + } + + public SLF4JLoggingException(final Exception ex) { + super(ex); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JServiceProvider.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JServiceProvider.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JServiceProvider.java index 332d16d..561132f 100644 --- a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JServiceProvider.java +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/SLF4JServiceProvider.java @@ -25,7 +25,7 @@ public class SLF4JServiceProvider implements org.slf4j.spi.SLF4JServiceProvider public static final String REQUESTED_API_VERSION = "1.8.99"; private ILoggerFactory loggerFactory; - private IMarkerFactory markerFactory; + private Log4jMarkerFactory markerFactory; private MDCAdapter mdcAdapter; @Override @@ -50,8 +50,10 @@ public class SLF4JServiceProvider implements org.slf4j.spi.SLF4JServiceProvider @Override public void initialize() { - loggerFactory = new Log4jLoggerFactory(); markerFactory = new Log4jMarkerFactory(); + loggerFactory = new Log4jLoggerFactory(markerFactory); mdcAdapter = new Log4jMDCAdapter(); } + + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/package-info.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/package-info.java b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/package-info.java new file mode 100644 index 0000000..ec0f031 --- /dev/null +++ b/log4j-slf4j18-impl/src/main/java/org/apache/logging/slf4j/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ +/** + * SLF4J support. Note that this does indeed share the same package namespace as the one found in log4j-to-slf4j; + * this is intentional. The two JARs should <em>not</em> be used at the same time! Thus, in an OSGi environment + * where split packages are not allowed, this error is prevented due to both JARs sharing an exported package name. + */ +package org.apache.logging.slf4j; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/Log4jMarkerTest.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/Log4jMarkerTest.java b/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/Log4jMarkerTest.java index af7c394..ac6ad22 100644 --- a/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/Log4jMarkerTest.java +++ b/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/Log4jMarkerTest.java @@ -19,17 +19,26 @@ package org.apache.logging.slf4j; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.MarkerManager; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; public class Log4jMarkerTest { + private static Log4jMarkerFactory markerFactory; + + @BeforeClass + public static void startup() { + markerFactory = ((Log4jLoggerFactory) org.slf4j.LoggerFactory.getILoggerFactory()).getMarkerFactory(); + + } + @Test public void testEquals() { final Marker markerA = MarkerManager.getMarker(Log4jMarkerTest.class.getName() + "-A"); final Marker markerB = MarkerManager.getMarker(Log4jMarkerTest.class.getName() + "-B"); - final Log4jMarker marker1 = new Log4jMarker(markerA); - final Log4jMarker marker2 = new Log4jMarker(markerA); - final Log4jMarker marker3 = new Log4jMarker(markerB); + final Log4jMarker marker1 = new Log4jMarker(markerFactory, markerA); + final Log4jMarker marker2 = new Log4jMarker(markerFactory, markerA); + final Log4jMarker marker3 = new Log4jMarker(markerFactory, markerB); Assert.assertEquals(marker1, marker2); Assert.assertNotEquals(marker1, null); Assert.assertNotEquals(null, marker1); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ebbd84d/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/MarkerTest.java ---------------------------------------------------------------------- diff --git a/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/MarkerTest.java b/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/MarkerTest.java index 6ef3846..c078fe0 100644 --- a/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/MarkerTest.java +++ b/log4j-slf4j18-impl/src/test/java/org/apache/logging/slf4j/MarkerTest.java @@ -21,6 +21,7 @@ import org.apache.logging.log4j.MarkerManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; @@ -32,8 +33,15 @@ public class MarkerTest { private static final String CHILD_MAKER_NAME = MarkerTest.class.getSimpleName() + "-TEST"; private static final String PARENT_MARKER_NAME = MarkerTest.class.getSimpleName() + "-PARENT"; + private static Log4jMarkerFactory markerFactory; - @Before + @BeforeClass + public static void startup() { + markerFactory = ((Log4jLoggerFactory) org.slf4j.LoggerFactory.getILoggerFactory()).getMarkerFactory(); + + } + + @Before @After public void clearMarkers() { MarkerManager.clear(); @@ -65,8 +73,8 @@ public class MarkerTest { slf4jMarker.add(slf4jParent); final Marker log4jParent = MarkerManager.getMarker(parentMakerName); final Marker log4jMarker = MarkerManager.getMarker(childMarkerName); - final Log4jMarker log4jSlf4jParent = new Log4jMarker(log4jParent); - final Log4jMarker log4jSlf4jMarker = new Log4jMarker(log4jMarker); + final Log4jMarker log4jSlf4jParent = new Log4jMarker(markerFactory, log4jParent); + final Log4jMarker log4jSlf4jMarker = new Log4jMarker(markerFactory, log4jMarker); final org.slf4j.Marker nullMarker = null; try { log4jSlf4jParent.add(nullMarker); @@ -126,8 +134,8 @@ public class MarkerTest { slf4jMarker.add(slf4jParent); final Marker log4jParent = MarkerManager.getMarker(parentMakerName); final Marker log4jMarker = MarkerManager.getMarker(childMarkerName); - final Log4jMarker log4jSlf4jParent = new Log4jMarker(log4jParent); - final Log4jMarker log4jSlf4jMarker = new Log4jMarker(log4jMarker); + final Log4jMarker log4jSlf4jParent = new Log4jMarker(markerFactory, log4jParent); + final Log4jMarker log4jSlf4jMarker = new Log4jMarker(markerFactory, log4jMarker); final org.slf4j.Marker nullMarker = null; try { Assert.assertFalse(log4jSlf4jParent.contains(nullMarker)); @@ -152,8 +160,8 @@ public class MarkerTest { slf4jMarker.add(slf4jParent); final Marker log4jParent = MarkerManager.getMarker(parentMakerName); final Marker log4jMarker = MarkerManager.getMarker(childMarkerName); - final Log4jMarker log4jSlf4jParent = new Log4jMarker(log4jParent); - final Log4jMarker log4jSlf4jMarker = new Log4jMarker(log4jMarker); + final Log4jMarker log4jSlf4jParent = new Log4jMarker(markerFactory, log4jParent); + final Log4jMarker log4jSlf4jMarker = new Log4jMarker(markerFactory, log4jMarker); final String nullStr = null; Assert.assertFalse(log4jSlf4jParent.contains(nullStr)); Assert.assertFalse(log4jSlf4jMarker.contains(nullStr)); @@ -168,8 +176,8 @@ public class MarkerTest { slf4jMarker.add(slf4jParent); final Marker log4jParent = MarkerManager.getMarker(parentMakerName); final Marker log4jMarker = MarkerManager.getMarker(childMakerName); - final Log4jMarker log4jSlf4jParent = new Log4jMarker(log4jParent); - final Log4jMarker log4jSlf4jMarker = new Log4jMarker(log4jMarker); + final Log4jMarker log4jSlf4jParent = new Log4jMarker(markerFactory, log4jParent); + final Log4jMarker log4jSlf4jMarker = new Log4jMarker(markerFactory, log4jMarker); final org.slf4j.Marker nullMarker = null; Assert.assertFalse(log4jSlf4jParent.remove(nullMarker)); Assert.assertFalse(log4jSlf4jMarker.remove(nullMarker));
