This is an automated email from the ASF dual-hosted git repository.
rgoers pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/master by this push:
new 9f6a8b9 LOG4J2 - 1523 Add RewriteAppenderBuilder to Log4j 1.
9f6a8b9 is described below
commit 9f6a8b95a0bc60beea35645ce4d1610ae5eaa9de
Author: Ralph Goers <[email protected]>
AuthorDate: Sat Nov 30 23:17:18 2019 -0700
LOG4J2 - 1523 Add RewriteAppenderBuilder to Log4j 1.
---
.../src/main/java/org/apache/log4j/Category.java | 24 ++-
.../org/apache/log4j/bridge/LogEventAdapter.java | 139 ++++++-------
.../org/apache/log4j/bridge/LogEventWrapper.java | 216 +++++++++++++++++++++
.../apache/log4j/bridge/RewritePolicyAdapter.java | 48 +++++
.../apache/log4j/bridge/RewritePolicyWrapper.java | 44 +++++
.../org/apache/log4j/builders/BuilderManager.java | 28 ++-
.../log4j/builders/appender/AppenderBuilder.java | 4 +-
.../builders/appender/AsyncAppenderBuilder.java | 2 +-
.../builders/appender/ConsoleAppenderBuilder.java | 2 +-
.../appender/DailyRollingFileAppenderBuilder.java | 4 +-
.../builders/appender/FileAppenderBuilder.java | 4 +-
.../builders/appender/NullAppenderBuilder.java | 2 +-
...derBuilder.java => RewriteAppenderBuilder.java} | 120 +++++-------
.../appender/RollingFileAppenderBuilder.java | 2 +-
.../builders/appender/SyslogAppenderBuilder.java | 4 +-
.../RewritePolicyBuilder.java} | 16 +-
.../apache/log4j/config/Log4j1Configuration.java | 8 +
.../log4j/config/PropertiesConfiguration.java | 3 -
.../log4j/helpers/AppenderAttachableImpl.java | 17 ++
.../org/apache/log4j/helpers/OptionConverter.java | 25 +++
.../org/apache/log4j/rewrite/MapRewritePolicy.java | 122 ++++++++++++
.../log4j/rewrite/PropertyRewritePolicy.java | 121 ++++++++++++
.../org/apache/log4j/rewrite/RewritePolicy.java | 36 ++++
.../java/org/apache/log4j/spi/LoggingEvent.java | 31 +++
.../org/apache/log4j/xml/XmlConfiguration.java | 44 ++++-
.../log4j/config/MapRewriteAppenderTest.java | 79 ++++++++
.../apache/log4j/config/RewriteAppenderTest.java | 77 ++++++++
.../src/test/resources/log4j1-maprewrite.xml | 35 ++++
.../src/test/resources/log4j1-rewrite.xml | 36 ++++
29 files changed, 1122 insertions(+), 171 deletions(-)
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
index e0e5aef..2608c6c 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
@@ -29,6 +29,7 @@ import org.apache.log4j.or.ObjectRenderer;
import org.apache.log4j.or.RendererSupport;
import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.message.MapMessage;
import org.apache.logging.log4j.spi.ExtendedLogger;
import org.apache.logging.log4j.spi.LoggerContext;
import org.apache.logging.log4j.message.LocalizedMessage;
@@ -380,12 +381,15 @@ public class Category {
public void forcedLog(final String fqcn, final Priority level, final
Object message, final Throwable t) {
final org.apache.logging.log4j.Level lvl =
org.apache.logging.log4j.Level.toLevel(level.toString());
- ObjectRenderer renderer = get(message.getClass());
- final Message msg = message instanceof Message ? (Message) message :
renderer != null ?
- new RenderedMessage(renderer, message) : new
ObjectMessage(message);
if (logger instanceof ExtendedLogger) {
- ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, new
ObjectMessage(message), t);
+ @SuppressWarnings("unchecked")
+ Message msg = message instanceof Message ? (Message) message :
message instanceof Map ?
+ new MapMessage((Map) message) : new ObjectMessage(message);
+ ((ExtendedLogger) logger).logMessage(fqcn, lvl, null, msg, t);
} else {
+ ObjectRenderer renderer = get(message.getClass());
+ final Message msg = message instanceof Message ? (Message) message
: renderer != null ?
+ new RenderedMessage(renderer, message) : new
ObjectMessage(message);
logger.log(lvl, msg, t);
}
}
@@ -475,14 +479,16 @@ public class Category {
public void log(final Priority priority, final Object message, final
Throwable t) {
if (isEnabledFor(priority)) {
- final Message msg = new ObjectMessage(message);
+ @SuppressWarnings("unchecked")
+ final Message msg = message instanceof Map ? new MapMessage((Map)
message) : new ObjectMessage(message);
forcedLog(FQCN, priority, msg, t);
}
}
public void log(final Priority priority, final Object message) {
if (isEnabledFor(priority)) {
- final Message msg = new ObjectMessage(message);
+ @SuppressWarnings("unchecked")
+ final Message msg = message instanceof Map ? new MapMessage((Map)
message) : new ObjectMessage(message);
forcedLog(FQCN, priority, msg, null);
}
}
@@ -497,10 +503,12 @@ public class Category {
private void maybeLog(final String fqcn, final
org.apache.logging.log4j.Level level,
final Object message, final Throwable throwable) {
if (logger.isEnabled(level)) {
+ @SuppressWarnings("unchecked")
+ Message msg = message instanceof Map ? new MapMessage((Map)
message) : new ObjectMessage(message);
if (logger instanceof ExtendedLogger) {
- ((ExtendedLogger) logger).logMessage(fqcn, level, null, new
ObjectMessage(message), throwable);
+ ((ExtendedLogger) logger).logMessage(fqcn, level, null, msg,
throwable);
} else {
- logger.log(level, message, throwable);
+ logger.log(level, msg, throwable);
}
}
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java
index 9ad4d27..9de0476 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java
@@ -16,8 +16,6 @@
*/
package org.apache.log4j.bridge;
-import java.lang.reflect.Method;
-
import org.apache.log4j.Category;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LocationInfo;
@@ -29,6 +27,10 @@ import org.apache.logging.log4j.core.util.Throwables;
import org.apache.logging.log4j.spi.StandardLevel;
import org.apache.logging.log4j.status.StatusLogger;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Set;
+
/**
* Converts a Log4j 2 LogEvent into the components needed by a Log4j 1.x
LoggingEvent.
* This class requires Log4j 2.
@@ -43,13 +45,47 @@ public class LogEventAdapter extends LoggingEvent {
this.event = event;
}
+ /**
+ * Returns the time when the application started, in milliseconds
+ * elapsed since 01.01.1970.
+ */
+ public static long getStartTime() {
+ return JVM_START_TIME;
+ }
+
+ /**
+ * Returns the result of {@code
ManagementFactory.getRuntimeMXBean().getStartTime()},
+ * or the current system time if JMX is not available.
+ */
+ private static long initStartTime() {
+ // We'd like to call
ManagementFactory.getRuntimeMXBean().getStartTime(),
+ // but Google App Engine throws a java.lang.NoClassDefFoundError
+ // "java.lang.management.ManagementFactory is a restricted class".
+ // The reflection is necessary because without it, Google App Engine
+ // will refuse to initialize this class.
+ try {
+ final Class<?> factoryClass =
Loader.loadSystemClass("java.lang.management.ManagementFactory");
+ final Method getRuntimeMXBean =
factoryClass.getMethod("getRuntimeMXBean");
+ final Object runtimeMXBean = getRuntimeMXBean.invoke(null);
+
+ final Class<?> runtimeMXBeanClass =
Loader.loadSystemClass("java.lang.management.RuntimeMXBean");
+ final Method getStartTime =
runtimeMXBeanClass.getMethod("getStartTime");
+ return (Long) getStartTime.invoke(runtimeMXBean);
+ } catch (final Throwable t) {
+ StatusLogger.getLogger().error("Unable to call
ManagementFactory.getRuntimeMXBean().getStartTime(), "
+ + "using system time for OnStartupTriggeringPolicy", t);
+ // We have little option but to declare "now" as the beginning of
time.
+ return System.currentTimeMillis();
+ }
+ }
+
public LogEvent getEvent() {
return this.event;
}
/**
- Set the location information for this logging event. The collected
- information is cached for future use.
+ * Set the location information for this logging event. The collected
+ * information is cached for future use.
*/
@Override
public LocationInfo getLocationInformation() {
@@ -58,7 +94,8 @@ public class LogEventAdapter extends LoggingEvent {
/**
* Return the level of this event. Use this form instead of directly
- * accessing the <code>level</code> field. */
+ * accessing the <code>level</code> field.
+ */
@Override
public Level getLevel() {
switch (StandardLevel.getStandardLevel(event.getLevel().intLevel())) {
@@ -70,8 +107,6 @@ public class LogEventAdapter extends LoggingEvent {
return Level.INFO;
case WARN:
return Level.WARN;
- case ERROR:
- return Level.ERROR;
case FATAL:
return Level.FATAL;
case OFF:
@@ -104,27 +139,23 @@ public class LogEventAdapter extends LoggingEvent {
Return the message for this logging event.
*/
@Override
- public
- Object getMessage() {
- return event.getMessage().getFormattedMessage();
+ public Object getMessage() {
+ return event.getMessage();
}
/*
* This method returns the NDC for this event.
*/
@Override
- public
- String getNDC() {
+ public String getNDC() {
return event.getContextStack().toString();
}
-
/*
Returns the the context corresponding to the <code>key</code> parameter.
*/
@Override
- public
- Object getMDC(String key) {
+ public Object getMDC(String key) {
if (event.getContextData() != null) {
return event.getContextData().getValue(key);
} else {
@@ -133,44 +164,34 @@ public class LogEventAdapter extends LoggingEvent {
}
/**
- Obtain a copy of this thread's MDC prior to serialization or
- asynchronous logging.
+ * Obtain a copy of this thread's MDC prior to serialization or
+ * asynchronous logging.
*/
@Override
- public
- void getMDCCopy() {
+ public void getMDCCopy() {
}
@Override
- public
- String getRenderedMessage() {
+ public String getRenderedMessage() {
return event.getMessage().getFormattedMessage();
}
- /**
- Returns the time when the application started, in milliseconds
- elapsed since 01.01.1970. */
- public static long getStartTime() {
- return JVM_START_TIME;
- }
-
@Override
- public
- String getThreadName() {
+ public String getThreadName() {
return event.getThreadName();
}
/**
- Returns the throwable information contained within this
- event. May be <code>null</code> if there is no such information.
-
- <p>Note that the {@link Throwable} object contained within a
- {@link ThrowableInformation} does not survive serialization.
-
- @since 1.1 */
+ * Returns the throwable information contained within this
+ * event. May be <code>null</code> if there is no such information.
+ *
+ * <p>Note that the {@link Throwable} object contained within a
+ * {@link ThrowableInformation} does not survive serialization.
+ *
+ * @since 1.1
+ */
@Override
- public
- ThrowableInformation getThrowableInformation() {
+ public ThrowableInformation getThrowableInformation() {
if (event.getThrown() != null) {
return new ThrowableInformation(event.getThrown());
}
@@ -178,40 +199,28 @@ public class LogEventAdapter extends LoggingEvent {
}
/**
- Return this event's throwable's string[] representaion.
+ * Return this event's throwable's string[] representaion.
*/
@Override
- public
- String[] getThrowableStrRep() {
+ public String[] getThrowableStrRep() {
if (event.getThrown() != null) {
return Throwables.toStringList(event.getThrown()).toArray(new
String[0]);
}
return null;
}
- /**
- * Returns the result of {@code
ManagementFactory.getRuntimeMXBean().getStartTime()},
- * or the current system time if JMX is not available.
- */
- private static long initStartTime() {
- // We'd like to call
ManagementFactory.getRuntimeMXBean().getStartTime(),
- // but Google App Engine throws a java.lang.NoClassDefFoundError
- // "java.lang.management.ManagementFactory is a restricted class".
- // The reflection is necessary because without it, Google App Engine
- // will refuse to initialize this class.
- try {
- final Class<?> factoryClass =
Loader.loadSystemClass("java.lang.management.ManagementFactory");
- final Method getRuntimeMXBean =
factoryClass.getMethod("getRuntimeMXBean");
- final Object runtimeMXBean = getRuntimeMXBean.invoke(null);
+ @Override
+ public String getProperty(final String key) {
+ return event.getContextData().getValue(key);
+ }
- final Class<?> runtimeMXBeanClass =
Loader.loadSystemClass("java.lang.management.RuntimeMXBean");
- final Method getStartTime =
runtimeMXBeanClass.getMethod("getStartTime");
- return (Long) getStartTime.invoke(runtimeMXBean);
- } catch (final Throwable t) {
- StatusLogger.getLogger().error("Unable to call
ManagementFactory.getRuntimeMXBean().getStartTime(), "
- + "using system time for OnStartupTriggeringPolicy", t);
- // We have little option but to declare "now" as the beginning of
time.
- return System.currentTimeMillis();
- }
+ @Override
+ public Set getPropertyKeySet() {
+ return event.getContextData().toMap().keySet();
+ }
+
+ @Override
+ public Map getProperties() {
+ return event.getContextData().toMap();
}
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java
new file mode 100644
index 0000000..1e46e12
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java
@@ -0,0 +1,216 @@
+/*
+ * 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.log4j.bridge;
+
+import org.apache.log4j.NDC;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.core.time.Instant;
+import org.apache.logging.log4j.core.time.MutableInstant;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.spi.MutableThreadContextStack;
+import org.apache.logging.log4j.util.BiConsumer;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.util.TriConsumer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Exposes a Log4j 1 logging event as a Log4j 2 LogEvent.
+ */
+public class LogEventWrapper implements LogEvent {
+
+ private final LoggingEvent event;
+ private final ContextDataMap contextData;
+ private final MutableThreadContextStack contextStack;
+ private volatile Thread thread;
+
+ public LogEventWrapper(LoggingEvent event) {
+ this.event = event;
+ this.contextData = new ContextDataMap(event.getProperties());
+ this.contextStack = new MutableThreadContextStack(NDC.cloneStack());
+ }
+
+ @Override
+ public LogEvent toImmutable() {
+ return null;
+ }
+
+ @Override
+ public ReadOnlyStringMap getContextData() {
+ return contextData;
+ }
+
+ @Override
+ public ThreadContext.ContextStack getContextStack() {
+ return contextStack;
+ }
+
+ @Override
+ public String getLoggerFqcn() {
+ return null;
+ }
+
+ @Override
+ public Level getLevel() {
+ return OptionConverter.convertLevel(event.getLevel());
+ }
+
+ @Override
+ public String getLoggerName() {
+ return event.getLoggerName();
+ }
+
+ @Override
+ public Marker getMarker() {
+ return null;
+ }
+
+ @Override
+ public Message getMessage() {
+ return new SimpleMessage(event.getRenderedMessage());
+ }
+
+ @Override
+ public long getTimeMillis() {
+ return event.getTimeStamp();
+ }
+
+ @Override
+ public Instant getInstant() {
+ MutableInstant mutable = new MutableInstant();
+ mutable.initFromEpochMilli(event.getTimeStamp(), 0);
+ return mutable;
+ }
+
+ @Override
+ public StackTraceElement getSource() {
+ LocationInfo info = event.getLocationInformation();
+ return new StackTraceElement(info.getClassName(),
info.getMethodName(), info.getFileName(),
+ Integer.parseInt(info.getLineNumber()));
+ }
+
+ @Override
+ public String getThreadName() {
+ return event.getThreadName();
+ }
+
+ @Override
+ public long getThreadId() {
+ Thread thread = getThread();
+ return thread != null ? thread.getId() : 0;
+ }
+
+ @Override
+ public int getThreadPriority() {
+ Thread thread = getThread();
+ return thread != null ? thread.getPriority() : 0;
+ }
+
+ private Thread getThread() {
+ if (thread == null) {
+ for (Thread thread : Thread.getAllStackTraces().keySet()) {
+ if (thread.getName().equals(event.getThreadName())) {
+ this.thread = thread;
+ return thread;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Throwable getThrown() {
+ if (event.getThrowableInformation() != null) {
+ return event.getThrowableInformation().getThrowable();
+ }
+ return null;
+ }
+
+ @Override
+ public ThrowableProxy getThrownProxy() {
+ return null;
+ }
+
+ @Override
+ public boolean isEndOfBatch() {
+ return false;
+ }
+
+ @Override
+ public boolean isIncludeLocation() {
+ return false;
+ }
+
+ @Override
+ public void setEndOfBatch(boolean endOfBatch) {
+
+ }
+
+ @Override
+ public void setIncludeLocation(boolean locationRequired) {
+
+ }
+
+ @Override
+ public long getNanoTime() {
+ return 0;
+ }
+
+
+ private static class ContextDataMap extends HashMap<String, String>
implements ReadOnlyStringMap {
+
+ ContextDataMap(Map<String, String> map) {
+ if (map != null) {
+ super.putAll(map);
+ }
+ }
+
+ @Override
+ public Map<String, String> toMap() {
+ return this;
+ }
+
+ @Override
+ public boolean containsKey(String key) {
+ return super.containsKey(key);
+ }
+
+ @Override
+ public <V> void forEach(BiConsumer<String, ? super V> action) {
+ super.forEach((k,v) -> action.accept(k, (V) v));
+ }
+
+ @Override
+ public <V, S> void forEach(TriConsumer<String, ? super V, S> action, S
state) {
+ super.forEach((k,v) -> action.accept(k, (V) v, state));
+ }
+
+ @Override
+ public <V> V getValue(String key) {
+ return (V) super.get(key);
+ }
+ }
+}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyAdapter.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyAdapter.java
new file mode 100644
index 0000000..cf0b42b
--- /dev/null
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyAdapter.java
@@ -0,0 +1,48 @@
+/*
+ * 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.log4j.bridge;
+
+import org.apache.log4j.rewrite.RewritePolicy;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.core.LogEvent;
+
+
+/**
+ * Binds a Log4j 1.x RewritePolicy to Log4j 2.
+ */
+public class RewritePolicyAdapter implements
org.apache.logging.log4j.core.appender.rewrite.RewritePolicy {
+
+ private final RewritePolicy policy;
+
+ /**
+ * Constructor.
+ */
+ public RewritePolicyAdapter(RewritePolicy policy) {
+ this.policy = policy;
+ }
+
+ @Override
+ public LogEvent rewrite(LogEvent source) {
+ LoggingEvent event = policy.rewrite(new LogEventAdapter(source));
+ return event instanceof LogEventAdapter ? ((LogEventAdapter)
event).getEvent() : new LogEventWrapper(event);
+ }
+
+ public RewritePolicy getPolicy() {
+ return this.policy;
+ }
+
+}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyWrapper.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyWrapper.java
new file mode 100644
index 0000000..e0994e1
--- /dev/null
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/RewritePolicyWrapper.java
@@ -0,0 +1,44 @@
+/*
+ * 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.log4j.bridge;
+
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.log4j.rewrite.RewritePolicy;
+
+/**
+ * Binds a Log4j 2 RewritePolicy to Log4j 1.
+ */
+public class RewritePolicyWrapper implements RewritePolicy {
+
+ private final org.apache.logging.log4j.core.appender.rewrite.RewritePolicy
policy;
+
+ public
RewritePolicyWrapper(org.apache.logging.log4j.core.appender.rewrite.RewritePolicy
policy) {
+ this.policy = policy;
+ }
+
+ @Override
+ public LoggingEvent rewrite(LoggingEvent source) {
+ LogEvent event = source instanceof LogEventAdapter ?
((LogEventAdapter) source).getEvent() :
+ new LogEventWrapper(source);
+ return new LogEventAdapter(policy.rewrite(event));
+ }
+
+ public org.apache.logging.log4j.core.appender.rewrite.RewritePolicy
getPolicy() {
+ return policy;
+ }
+}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
index d6465f0..3319bf0 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
@@ -21,7 +21,9 @@ import org.apache.log4j.Layout;
import org.apache.log4j.builders.appender.AppenderBuilder;
import org.apache.log4j.builders.filter.FilterBuilder;
import org.apache.log4j.builders.layout.LayoutBuilder;
+import org.apache.log4j.builders.rewrite.RewritePolicyBuilder;
import org.apache.log4j.config.PropertiesConfiguration;
+import org.apache.log4j.rewrite.RewritePolicy;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.xml.XmlConfiguration;
import org.apache.logging.log4j.Logger;
@@ -72,7 +74,7 @@ public class BuilderManager {
if (plugin != null) {
AppenderBuilder builder = createBuilder(plugin, prefix, props);
if (builder != null) {
- return builder.parseAppender(name, layoutPrefix, filterPrefix,
props, config);
+ return builder.parseAppender(name, prefix, layoutPrefix,
filterPrefix, props, config);
}
}
return null;
@@ -127,6 +129,30 @@ public class BuilderManager {
return null;
}
+ public RewritePolicy parseRewritePolicy(String className, Element
rewriteElement, XmlConfiguration config) {
+ PluginType<?> plugin = plugins.get(className.toLowerCase());
+ if (plugin != null) {
+ try {
+ @SuppressWarnings("unchecked")
+ RewritePolicyBuilder builder = (RewritePolicyBuilder)
LoaderUtil.newInstanceOf(plugin.getPluginClass());
+ return builder.parseRewritePolicy(rewriteElement, config);
+ } catch (InstantiationException | IllegalAccessException |
InvocationTargetException ex) {
+ LOGGER.warn("Unable to load plugin: {} due to: {}",
plugin.getKey(), ex.getMessage());
+ }
+ }
+ return null;
+ }
+ public RewritePolicy parseRewritePolicy(String className, String
policyPrefix, Properties props, PropertiesConfiguration config) {
+ PluginType<?> plugin = plugins.get(className.toLowerCase());
+ if (plugin != null) {
+ RewritePolicyBuilder builder = createBuilder(plugin, policyPrefix,
props);
+ if (builder != null) {
+ return builder.parseRewritePolicy(config);
+ }
+ }
+ return null;
+ }
+
private <T extends AbstractBuilder> T createBuilder(PluginType<?> plugin,
String prefix, Properties props) {
try {
Class<?> clazz = plugin.getPluginClass();
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
index 0572b86..bb7ff93 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
@@ -30,7 +30,7 @@ public interface AppenderBuilder {
Appender parseAppender(Element element, XmlConfiguration configuration);
- Appender parseAppender(String name, String layoutPrefix, String
filterPrefix, Properties props,
- PropertiesConfiguration configuration);
+ Appender parseAppender(String name, String appenderPrefix, String
layoutPrefix, String filterPrefix,
+ Properties props, PropertiesConfiguration configuration);
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
index 86969ed..e60d50b 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
@@ -126,7 +126,7 @@ public class AsyncAppenderBuilder extends AbstractBuilder
implements AppenderBui
}
@Override
- public Appender parseAppender(final String name, final String layoutPrefix,
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
String appenderRef = getProperty(APPENDER_REF_TAG);
boolean blocking = getBooleanProperty(BLOCKING_PARAM);
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/ConsoleAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/ConsoleAppenderBuilder.java
index 423fab7..119e6fb 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/ConsoleAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/ConsoleAppenderBuilder.java
@@ -129,7 +129,7 @@ public class ConsoleAppenderBuilder extends AbstractBuilder
implements AppenderB
}
@Override
- public Appender parseAppender(final String name, final String layoutPrefix,
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
Layout layout = configuration.parseLayout(layoutPrefix, name, props);
Filter filter = configuration.parseAppenderFilters(props,
filterPrefix, name);
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/DailyRollingFileAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/DailyRollingFileAppenderBuilder.java
index 1dd1885..89c2dba 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/DailyRollingFileAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/DailyRollingFileAppenderBuilder.java
@@ -136,8 +136,8 @@ public class DailyRollingFileAppenderBuilder extends
AbstractBuilder implements
}
@Override
- public Appender parseAppender(final String name, final String
layoutPrefix, final String filterPrefix,
- final Properties props, final PropertiesConfiguration
configuration) {
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
+ final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
Layout layout = configuration.parseLayout(layoutPrefix, name, props);
Filter filter = configuration.parseAppenderFilters(props,
filterPrefix, name);
String fileName = getProperty(FILE_PARAM);
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/FileAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/FileAppenderBuilder.java
index 9d108c2..8b7f467 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/FileAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/FileAppenderBuilder.java
@@ -132,8 +132,8 @@ public class FileAppenderBuilder extends AbstractBuilder
implements AppenderBuil
@Override
- public Appender parseAppender(final String name, final String
layoutPrefix, final String filterPrefix,
- final Properties props, final PropertiesConfiguration
configuration) {
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
+ final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
Layout layout = configuration.parseLayout(layoutPrefix, name, props);
Filter filter = configuration.parseAppenderFilters(props,
filterPrefix, name);
String level = getProperty(THRESHOLD_PARAM);
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/NullAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/NullAppenderBuilder.java
index 8b69d39..07f2fd5 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/NullAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/NullAppenderBuilder.java
@@ -46,7 +46,7 @@ public class NullAppenderBuilder implements AppenderBuilder {
@Override
- public Appender parseAppender(final String name, final String layoutPrefix,
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
return new AppenderWrapper(NullAppender.createAppender(name));
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RewriteAppenderBuilder.java
similarity index 54%
copy from
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
copy to
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RewriteAppenderBuilder.java
index 86969ed..37ac70f 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AsyncAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RewriteAppenderBuilder.java
@@ -18,15 +18,18 @@ package org.apache.log4j.builders.appender;
import org.apache.log4j.Appender;
import org.apache.log4j.bridge.AppenderWrapper;
+import org.apache.log4j.bridge.RewritePolicyAdapter;
+import org.apache.log4j.bridge.RewritePolicyWrapper;
import org.apache.log4j.builders.AbstractBuilder;
-import org.apache.log4j.builders.BooleanHolder;
import org.apache.log4j.builders.Holder;
import org.apache.log4j.config.Log4j1Configuration;
import org.apache.log4j.config.PropertiesConfiguration;
import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.rewrite.RewritePolicy;
+import org.apache.log4j.spi.Filter;
import org.apache.log4j.xml.XmlConfiguration;
import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.appender.AsyncAppender;
+import org.apache.logging.log4j.core.appender.rewrite.RewriteAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.plugins.Plugin;
import org.apache.logging.log4j.status.StatusLogger;
@@ -37,28 +40,28 @@ import java.util.List;
import java.util.Properties;
import static org.apache.log4j.builders.BuilderManager.CATEGORY;
+import static org.apache.log4j.config.Log4j1Configuration.APPENDER_REF_TAG;
+import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
+import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG;
import static org.apache.log4j.xml.XmlConfiguration.NAME_ATTR;
import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG;
import static org.apache.log4j.xml.XmlConfiguration.VALUE_ATTR;
import static org.apache.log4j.xml.XmlConfiguration.forEachElement;
-import static org.apache.log4j.config.Log4j1Configuration.APPENDER_REF_TAG;
-import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM;
/**
* Build an Asynch Appender
*/
-@Plugin(name = "org.apache.log4j.AsyncAppender", category = CATEGORY)
-public class AsyncAppenderBuilder extends AbstractBuilder implements
AppenderBuilder {
+@Plugin(name = "org.apache.log4j.rewrite.RewriteAppender", category = CATEGORY)
+public class RewriteAppenderBuilder extends AbstractBuilder implements
AppenderBuilder {
private static final Logger LOGGER = StatusLogger.getLogger();
- private static final String BLOCKING_PARAM = "Blocking";
- private static final String INCLUDE_LOCATION_PARAM = "IncludeLocation";
+ private static final String REWRITE_POLICY_TAG = "rewritePolicy";
- public AsyncAppenderBuilder() {
+ public RewriteAppenderBuilder() {
}
- public AsyncAppenderBuilder(String prefix, Properties props) {
+ public RewriteAppenderBuilder(String prefix, Properties props) {
super(prefix, props);
}
@@ -66,10 +69,9 @@ public class AsyncAppenderBuilder extends AbstractBuilder
implements AppenderBui
public Appender parseAppender(final Element appenderElement, final
XmlConfiguration config) {
String name = appenderElement.getAttribute(NAME_ATTR);
Holder<List<String>> appenderRefs = new Holder<>(new ArrayList<>());
- Holder<Boolean> blocking = new BooleanHolder();
- Holder<Boolean> includeLocation = new BooleanHolder();
- Holder<String> level = new Holder<>("trace");
- Holder<Integer> bufferSize = new Holder<>(1024);
+ Holder<RewritePolicy> rewritePolicyHolder = new Holder<>();
+ Holder<String> level = new Holder<>();
+ Holder<Filter> filter = new Holder<>();
forEachElement(appenderElement.getChildNodes(), (currentElement) -> {
switch (currentElement.getTagName()) {
case APPENDER_REF_TAG:
@@ -78,61 +80,44 @@ public class AsyncAppenderBuilder extends AbstractBuilder
implements AppenderBui
appenderRefs.get().add(appender.getName());
}
break;
+ case REWRITE_POLICY_TAG: {
+ RewritePolicy policy =
config.parseRewritePolicy(currentElement);
+ if (policy != null) {
+ rewritePolicyHolder.set(policy);
+ }
+ break;
+ }
+ case FILTER_TAG: {
+ filter.set(config.parseFilters(currentElement));
+ break;
+ }
case PARAM_TAG: {
- switch (currentElement.getAttribute(NAME_ATTR)) {
- case BUFFER_SIZE_PARAM: {
- String value =
currentElement.getAttribute(VALUE_ATTR);
- if (value == null) {
- LOGGER.warn("No value supplied for BufferSize
parameter. Defaulting to 1024.");
- } else {
- bufferSize.set(Integer.parseInt(value));
- }
- break;
- }
- case BLOCKING_PARAM: {
- String value =
currentElement.getAttribute(VALUE_ATTR);
- if (value == null) {
- LOGGER.warn("No value supplied for Blocking
parameter. Defaulting to false.");
- } else {
- blocking.set(Boolean.parseBoolean(value));
- }
- break;
- }
- case INCLUDE_LOCATION_PARAM: {
- String value =
currentElement.getAttribute(VALUE_ATTR);
- if (value == null) {
- LOGGER.warn("No value supplied for
IncludeLocation parameter. Defaulting to false.");
- } else {
-
includeLocation.set(Boolean.parseBoolean(value));
- }
- break;
- }
- case THRESHOLD_PARAM: {
- String value =
currentElement.getAttribute(VALUE_ATTR);
- if (value == null) {
- LOGGER.warn("No value supplied for Threshold
parameter, ignoring.");
- } else {
- level.set(value);
- }
- break;
+ if
(currentElement.getAttribute(NAME_ATTR).equalsIgnoreCase(THRESHOLD_PARAM)) {
+ String value = currentElement.getAttribute(VALUE_ATTR);
+ if (value == null) {
+ LOGGER.warn("No value supplied for Threshold
parameter, ignoring.");
+ } else {
+ level.set(value);
}
}
break;
}
}
});
- return createAppender(name, level.get(),
appenderRefs.get().toArray(new String[0]), blocking.get(),
- bufferSize.get(), includeLocation.get(), config);
+ return createAppender(name, level.get(),
appenderRefs.get().toArray(new String[0]), rewritePolicyHolder.get(),
+ filter.get(), config);
}
@Override
- public Appender parseAppender(final String name, final String layoutPrefix,
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
String appenderRef = getProperty(APPENDER_REF_TAG);
- boolean blocking = getBooleanProperty(BLOCKING_PARAM);
- boolean includeLocation = getBooleanProperty(INCLUDE_LOCATION_PARAM);
+ Filter filter = configuration.parseAppenderFilters(props,
filterPrefix, name);
+ String policyPrefix = appenderPrefix + ".rewritePolicy";
+ String className = getProperty(policyPrefix);
+ RewritePolicy policy =
configuration.getBuilderManager().parseRewritePolicy(className, policyPrefix,
+ props, configuration);
String level = getProperty(THRESHOLD_PARAM);
- int bufferSize = getIntegerProperty(BUFFER_SIZE_PARAM, 1024);
if (appenderRef == null) {
LOGGER.warn("No appender references configured for AsyncAppender
{}", name);
return null;
@@ -142,13 +127,11 @@ public class AsyncAppenderBuilder extends AbstractBuilder
implements AppenderBui
LOGGER.warn("Cannot locate Appender {}", appenderRef);
return null;
}
- return createAppender(name, level, new String[] {appenderRef},
blocking, bufferSize, includeLocation,
- configuration);
+ return createAppender(name, level, new String[] {appenderRef}, policy,
filter, configuration);
}
private <T extends Log4j1Configuration> Appender createAppender(String
name, String level,
- String[] appenderRefs, boolean blocking, int bufferSize, boolean
includeLocation,
- T configuration) {
+ String[] appenderRefs, RewritePolicy policy, Filter filter, T
configuration) {
org.apache.logging.log4j.Level logLevel =
OptionConverter.convertLevel(level,
org.apache.logging.log4j.Level.TRACE);
AppenderRef[] refs = new AppenderRef[appenderRefs.length];
@@ -156,13 +139,14 @@ public class AsyncAppenderBuilder extends AbstractBuilder
implements AppenderBui
for (String appenderRef : appenderRefs) {
refs[index++] = AppenderRef.createAppenderRef(appenderRef,
logLevel, null);
}
- return new AppenderWrapper(AsyncAppender.newBuilder()
- .setName(name)
- .setAppenderRefs(refs)
- .setBlocking(blocking)
- .setBufferSize(bufferSize)
- .setIncludeLocation(includeLocation)
- .setConfiguration(configuration)
- .build());
+ org.apache.logging.log4j.core.Filter rewriteFilter =
buildFilters(level, filter);
+ org.apache.logging.log4j.core.appender.rewrite.RewritePolicy
rewritePolicy;
+ if (policy instanceof RewritePolicyWrapper) {
+ rewritePolicy = ((RewritePolicyWrapper) policy).getPolicy();
+ } else {
+ rewritePolicy = new RewritePolicyAdapter(policy);
+ }
+ return new AppenderWrapper(RewriteAppender.createAppender(name, true,
refs, configuration,
+ rewritePolicy, rewriteFilter));
}
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java
index ccc8099..bac9425 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java
@@ -158,7 +158,7 @@ public class RollingFileAppenderBuilder extends
AbstractBuilder implements Appen
@Override
- public Appender parseAppender(final String name, final String layoutPrefix,
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
Layout layout = configuration.parseLayout(layoutPrefix, name, props);
Filter filter = configuration.parseAppenderFilters(props,
filterPrefix, name);
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/SyslogAppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/SyslogAppenderBuilder.java
index 0600279..c281ea9 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/SyslogAppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/SyslogAppenderBuilder.java
@@ -110,8 +110,8 @@ public class SyslogAppenderBuilder extends AbstractBuilder
implements AppenderBu
@Override
- public Appender parseAppender(final String name, final String
layoutPrefix, final String filterPrefix,
- final Properties props, final PropertiesConfiguration
configuration) {
+ public Appender parseAppender(final String name, final String
appenderPrefix, final String layoutPrefix,
+ final String filterPrefix, final Properties props, final
PropertiesConfiguration configuration) {
Filter filter = configuration.parseAppenderFilters(props,
filterPrefix, name);
Layout layout = configuration.parseLayout(layoutPrefix, name, props);
String level = getProperty(THRESHOLD_PARAM);
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java
similarity index 70%
copy from
log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
copy to
log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java
index 0572b86..5ca196a 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java
@@ -14,23 +14,19 @@
* See the license for the specific language governing permissions and
* limitations under the license.
*/
-package org.apache.log4j.builders.appender;
+package org.apache.log4j.builders.rewrite;
-import org.apache.log4j.Appender;
import org.apache.log4j.config.PropertiesConfiguration;
+import org.apache.log4j.rewrite.RewritePolicy;
import org.apache.log4j.xml.XmlConfiguration;
import org.w3c.dom.Element;
-import java.util.Properties;
-
/**
- * Define an Appender Builder.
+ * Define a RewritePolicy Builder.
*/
-public interface AppenderBuilder {
-
- Appender parseAppender(Element element, XmlConfiguration configuration);
+public interface RewritePolicyBuilder {
- Appender parseAppender(String name, String layoutPrefix, String
filterPrefix, Properties props,
- PropertiesConfiguration configuration);
+ RewritePolicy parseRewritePolicy(Element element, XmlConfiguration config);
+ RewritePolicy parseRewritePolicy(PropertiesConfiguration config);
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1Configuration.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1Configuration.java
index 021afa3..9236006 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1Configuration.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1Configuration.java
@@ -16,6 +16,7 @@
*/
package org.apache.log4j.config;
+import org.apache.log4j.builders.BuilderManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.config.Configuration;
@@ -35,12 +36,19 @@ public class Log4j1Configuration extends
AbstractConfiguration implements Reconf
public static final String NULL = "null";
+ protected final BuilderManager manager;
+
public Log4j1Configuration(final LoggerContext loggerContext, final
ConfigurationSource source,
int monitorIntervalSeconds) {
super(loggerContext, source);
+ manager = new BuilderManager();
initializeWatchers(this, source, monitorIntervalSeconds);
}
+ public BuilderManager getBuilderManager() {
+ return manager;
+ }
+
/**
* Initialize the configuration.
*/
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
index c3e995d..2f7ac58 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
@@ -66,8 +66,6 @@ public class PropertiesConfiguration extends
Log4j1Configuration {
private final Map<String, Appender> registry;
- private final BuilderManager manager;
-
/**
* No argument constructor.
*/
@@ -75,7 +73,6 @@ public class PropertiesConfiguration extends
Log4j1Configuration {
int monitorIntervalSeconds) {
super(loggerContext, source, monitorIntervalSeconds);
registry = new HashMap<>();
- manager = new BuilderManager();
}
public void doConfigure() {
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
index fe9530d..e9e35f9 100644
---
a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/AppenderAttachableImpl.java
@@ -18,6 +18,7 @@ package org.apache.log4j.helpers;
import org.apache.log4j.Appender;
import org.apache.log4j.spi.AppenderAttachable;
+import org.apache.log4j.spi.LoggingEvent;
import java.util.Collections;
import java.util.Enumeration;
@@ -67,4 +68,20 @@ public class AppenderAttachableImpl implements
AppenderAttachable {
public void removeAppender(String name) {
appenders.remove(name);
}
+
+ /**
+ * Call the <code>doAppend</code> method on all attached appenders.
+ */
+ public int appendLoopOnAppenders(LoggingEvent event) {
+ for (Appender appender : appenders.values()) {
+ appender.doAppend(event);
+ }
+ return appenders.size();
+ }
+
+ public void close() {
+ for (Appender appender : appenders.values()) {
+ appender.close();
+ }
+ }
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
index e09e26b..5f910fa 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java
@@ -20,6 +20,7 @@ package org.apache.log4j.helpers;
import org.apache.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.spi.StandardLevel;
import org.apache.logging.log4j.util.LoaderUtil;
import java.io.InterruptedIOException;
@@ -358,6 +359,30 @@ public class OptionConverter {
return org.apache.logging.log4j.Level.ALL;
}
+ public static Level convertLevel(org.apache.logging.log4j.Level level) {
+ if (level == null) {
+ return Level.ERROR;
+ }
+ switch (level.getStandardLevel()) {
+ case FATAL:
+ return Level.FATAL;
+ case WARN:
+ return Level.WARN;
+ case INFO:
+ return Level.INFO;
+ case DEBUG:
+ return Level.DEBUG;
+ case TRACE:
+ return Level.TRACE;
+ case ALL:
+ return Level.ALL;
+ case OFF:
+ return Level.OFF;
+ default:
+ return Level.ERROR;
+ }
+ }
+
/**
* Find the value corresponding to <code>key</code> in
* <code>props</code>. Then perform variable substitution on the
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/MapRewritePolicy.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/MapRewritePolicy.java
new file mode 100644
index 0000000..4f53583
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/MapRewritePolicy.java
@@ -0,0 +1,122 @@
+/*
+ * 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.log4j.rewrite;
+
+import org.apache.log4j.bridge.LogEventAdapter;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.message.MapMessage;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This policy rewrites events where the message of the
+ * original event implements java.util.Map.
+ * All other events are passed through unmodified.
+ * If the map contains a "message" entry, the value will be
+ * used as the message for the rewritten event. The rewritten
+ * event will have a property set that is the combination of the
+ * original property set and the other members of the message map.
+ * If both the original property set and the message map
+ * contain the same entry, the value from the message map
+ * will overwrite the original property set.
+ * <p>
+ * The combination of the RewriteAppender and this policy
+ * performs the same actions as the MapFilter from log4j 1.3.
+ */
+public class MapRewritePolicy implements RewritePolicy {
+ /**
+ * {@inheritDoc}
+ */
+ public LoggingEvent rewrite(final LoggingEvent source) {
+ Object msg = source.getMessage();
+ if (msg instanceof MapMessage || msg instanceof Map) {
+ Map<String, String> props = source.getProperties() != null ? new
HashMap<>(source.getProperties())
+ : new HashMap<>();
+ @SuppressWarnings("unchecked")
+ Map<String, Object> eventProps = msg instanceof Map ? (Map) msg :
((MapMessage) msg).getData();
+ //
+ // if the map sent in the logging request
+ // has "message" entry, use that as the message body
+ // otherwise, use the entire map.
+ //
+ Message newMessage = null;
+ Object newMsg = eventProps.get("message");
+ if (newMsg != null) {
+ newMessage = new SimpleMessage(newMsg.toString());
+ for (Map.Entry<String, Object> entry : eventProps.entrySet()) {
+ if (!("message".equals(entry.getKey()))) {
+ props.put(entry.getKey(), entry.getValue().toString());
+ }
+ }
+ } else {
+ return source;
+ }
+
+ LogEvent event;
+ if (source instanceof LogEventAdapter) {
+ event = new Log4jLogEvent.Builder(((LogEventAdapter)
source).getEvent())
+ .setMessage(newMessage)
+ .setContextData(new SortedArrayStringMap(props))
+ .build();
+ } else {
+ LocationInfo info = source.getLocationInformation();
+ StackTraceElement element = new
StackTraceElement(info.getClassName(), info.getMethodName(),
+ info.getFileName(),
Integer.parseInt(info.getLineNumber()));
+ Thread thread = getThread(source.getThreadName());
+ long threadId = thread != null ? thread.getId() : 0;
+ int threadPriority = thread != null ? thread.getPriority() : 0;
+ event = Log4jLogEvent.newBuilder()
+ .setContextData(new SortedArrayStringMap(props))
+
.setLevel(OptionConverter.convertLevel(source.getLevel()))
+ .setLoggerFqcn(source.getFQNOfLoggerClass())
+ .setMarker(null)
+ .setMessage(newMessage)
+ .setSource(element)
+ .setLoggerName(source.getLoggerName())
+ .setThreadName(source.getThreadName())
+ .setThreadId(threadId)
+ .setThreadPriority(threadPriority)
+
.setThrown(source.getThrowableInformation().getThrowable())
+ .setTimeMillis(source.getTimeStamp())
+ .setNanoTime(0)
+ .setThrownProxy(null)
+ .build();
+ }
+ return new LogEventAdapter(event);
+ } else {
+ return source;
+ }
+
+ }
+
+ private Thread getThread(String name) {
+ for (Thread thread : Thread.getAllStackTraces().keySet()) {
+ if (thread.getName().equals(name)) {
+ return thread;
+ }
+ }
+ return null;
+ }
+}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/PropertyRewritePolicy.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/PropertyRewritePolicy.java
new file mode 100644
index 0000000..b822a99
--- /dev/null
+++
b/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/PropertyRewritePolicy.java
@@ -0,0 +1,121 @@
+/*
+ * 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.log4j.rewrite;
+
+import org.apache.log4j.bridge.LogEventAdapter;
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * This policy rewrites events by adding
+ * a user-specified list of properties to the event.
+ * Existing properties are not modified.
+ * <p>
+ * The combination of the RewriteAppender and this policy
+ * performs the same actions as the PropertyFilter from log4j 1.3.
+ */
+
+public class PropertyRewritePolicy implements RewritePolicy {
+ private Map<String, String> properties = Collections.EMPTY_MAP;
+
+ public PropertyRewritePolicy() {
+ }
+
+ /**
+ * Set a string representing the property name/value pairs.
+ * <p>
+ * Form: propname1=propvalue1,propname2=propvalue2
+ *
+ * @param props
+ */
+ public void setProperties(String props) {
+ Map hashTable = new HashMap();
+ StringTokenizer pairs = new StringTokenizer(props, ",");
+ while (pairs.hasMoreTokens()) {
+ StringTokenizer entry = new StringTokenizer(pairs.nextToken(),
"=");
+ hashTable.put(entry.nextElement().toString().trim(),
entry.nextElement().toString().trim());
+ }
+ synchronized (this) {
+ properties = hashTable;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public LoggingEvent rewrite(final LoggingEvent source) {
+ if (!properties.isEmpty()) {
+ Map<String, String> rewriteProps = source.getProperties() != null
? new HashMap<>(source.getProperties())
+ : new HashMap<>();
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ if (!rewriteProps.containsKey(entry.getKey())) {
+ rewriteProps.put(entry.getKey(), entry.getValue());
+ }
+ }
+ LogEvent event;
+ if (source instanceof LogEventAdapter) {
+ event = new Log4jLogEvent.Builder(((LogEventAdapter)
source).getEvent())
+ .setContextData(new SortedArrayStringMap(rewriteProps))
+ .build();
+ } else {
+ LocationInfo info = source.getLocationInformation();
+ StackTraceElement element = new
StackTraceElement(info.getClassName(), info.getMethodName(),
+ info.getFileName(),
Integer.parseInt(info.getLineNumber()));
+ Thread thread = getThread(source.getThreadName());
+ long threadId = thread != null ? thread.getId() : 0;
+ int threadPriority = thread != null ? thread.getPriority() : 0;
+ event = Log4jLogEvent.newBuilder()
+ .setContextData(new SortedArrayStringMap(rewriteProps))
+
.setLevel(OptionConverter.convertLevel(source.getLevel()))
+ .setLoggerFqcn(source.getFQNOfLoggerClass())
+ .setMarker(null)
+ .setMessage(new
SimpleMessage(source.getRenderedMessage()))
+ .setSource(element)
+ .setLoggerName(source.getLoggerName())
+ .setThreadName(source.getThreadName())
+ .setThreadId(threadId)
+ .setThreadPriority(threadPriority)
+
.setThrown(source.getThrowableInformation().getThrowable())
+ .setTimeMillis(source.getTimeStamp())
+ .setNanoTime(0)
+ .setThrownProxy(null)
+ .build();
+ }
+ return new LogEventAdapter(event);
+ }
+ return source;
+ }
+
+ private Thread getThread(String name) {
+ for (Thread thread : Thread.getAllStackTraces().keySet()) {
+ if (thread.getName().equals(name)) {
+ return thread;
+ }
+ }
+ return null;
+ }
+}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/RewritePolicy.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/RewritePolicy.java
new file mode 100644
index 0000000..9570218
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/rewrite/RewritePolicy.java
@@ -0,0 +1,36 @@
+/*
+ * 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.log4j.rewrite;
+
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+ * This interface is implemented to provide a rewrite
+ * strategy for RewriteAppender. RewriteAppender will
+ * call the rewrite method with a source logging event.
+ * The strategy may return that event, create a new event
+ * or return null to suppress the logging request.
+ */
+public interface RewritePolicy {
+ /**
+ * Rewrite a logging event.
+ * @param source a logging event that may be returned or
+ * used to create a new logging event.
+ * @return a logging event or null to suppress processing.
+ */
+ LoggingEvent rewrite(final LoggingEvent source);
+}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LoggingEvent.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LoggingEvent.java
index e9f57de..d7755a2 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LoggingEvent.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LoggingEvent.java
@@ -20,6 +20,9 @@ import org.apache.log4j.Category;
import org.apache.log4j.Level;
import org.apache.log4j.bridge.LogEventAdapter;
+import java.util.Map;
+import java.util.Set;
+
/**
* No-op version of Log4j 1.2 LoggingEvent. This class is not directly used
by Log4j 1.x clients but is used by
* the Log4j 2 LogEvent adapter to be compatible with Log4j 1.x components.
@@ -49,6 +52,14 @@ public class LoggingEvent {
return null;
}
+ public String getFQNOfLoggerClass() {
+ return null;
+ }
+
+ public final long getTimeStamp() {
+ return 0;
+ }
+
/**
* Gets the logger of the event.
* Use should be restricted to cloning events.
@@ -128,4 +139,24 @@ public class LoggingEvent {
return null;
}
+ public void setProperty(final String propName,
+ final String propValue) {
+
+ }
+
+ public String getProperty(final String key) {
+ return null;
+ }
+
+ public Set getPropertyKeySet() {
+ return null;
+ }
+
+ public Map getProperties() {
+ return null;
+ }
+
+ public Object removeProperty(String propName) {
+ return null;
+ }
}
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java
index c96c26d..a37f140 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java
@@ -21,10 +21,10 @@ import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.bridge.AppenderAdapter;
import org.apache.log4j.bridge.AppenderWrapper;
-import org.apache.log4j.builders.BuilderManager;
import org.apache.log4j.config.Log4j1Configuration;
import org.apache.log4j.config.PropertySetter;
import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.rewrite.RewritePolicy;
import org.apache.log4j.spi.AppenderAttachable;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.Filter;
@@ -99,8 +99,6 @@ public class XmlConfiguration extends Log4j1Configuration {
*/
protected static final String DEFAULT_PREFIX = "log4j";
- private final BuilderManager manager;
-
// key: appenderName, value: appender
private Map<String, Appender> appenderMap;
@@ -110,7 +108,6 @@ public class XmlConfiguration extends Log4j1Configuration {
int monitorIntervalSeconds) {
super(loggerContext, source, monitorIntervalSeconds);
appenderMap = new HashMap<>();
- manager = new BuilderManager();
}
public void addAppenderIfAbsent(Appender appender) {
@@ -415,6 +412,45 @@ public class XmlConfiguration extends Log4j1Configuration {
return null;
}
+
+ public RewritePolicy parseRewritePolicy(Element rewritePolicyElement) {
+
+ String className =
subst(rewritePolicyElement.getAttribute(CLASS_ATTR));
+ LOGGER.debug("Class name: [" + className + ']');
+ RewritePolicy policy = manager.parseRewritePolicy(className,
rewritePolicyElement, this);
+ if (policy == null) {
+ policy = buildRewritePolicy(className, rewritePolicyElement);
+ }
+ return policy;
+ }
+
+ private RewritePolicy buildRewritePolicy(String className, Element
element) {
+ try {
+ RewritePolicy policy = LoaderUtil.newInstanceOf(className);
+ PropertySetter propSetter = new PropertySetter(policy);
+
+ forEachElement(element.getChildNodes(), (currentElement) -> {
+ if (currentElement.getTagName().equalsIgnoreCase(PARAM_TAG)) {
+ setParameter(currentElement, propSetter);
+ }
+ });
+ propSetter.activate();
+ return policy;
+ } catch (ConsumerException ex) {
+ Throwable t = ex.getCause();
+ if (t instanceof InterruptedException || t instanceof
InterruptedIOException) {
+ Thread.currentThread().interrupt();
+ }
+ LOGGER.error("Could not create an RewritePolicy. Reported error
follows.", t);
+ } catch (Exception oops) {
+ if (oops instanceof InterruptedException || oops instanceof
InterruptedIOException) {
+ Thread.currentThread().interrupt();
+ }
+ LOGGER.error("Could not create an RewritePolicy. Reported error
follows.", oops);
+ }
+ return null;
+ }
+
/**
* Used internally to parse an {@link ErrorHandler} element.
*/
diff --git
a/log4j-1.2-api/src/test/java/org/apache/log4j/config/MapRewriteAppenderTest.java
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/MapRewriteAppenderTest.java
new file mode 100644
index 0000000..840971a
--- /dev/null
+++
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/MapRewriteAppenderTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.log4j.config;
+
+import org.apache.log4j.ListAppender;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.bridge.AppenderAdapter;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test RewriteAppender
+ */
+public class MapRewriteAppenderTest {
+
+ @BeforeClass
+ public static void beforeClass() {
+
System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY,
"target/test-classes/log4j1-mapRewrite.xml");
+ }
+
+ @After
+ public void after() {
+ ThreadContext.clearMap();
+ }
+
+ @Test
+ public void testRewrite() throws Exception {
+ Logger logger = LogManager.getLogger("test");
+ Map<String, String> map = new HashMap<>();
+ map.put("message", "This is a test");
+ map.put("hello", "world");
+ logger.debug(map);
+ LoggerContext context = (LoggerContext)
org.apache.logging.log4j.LogManager.getContext(false);
+ Configuration configuration = context.getConfiguration();
+ Map<String, Appender> appenders = configuration.getAppenders();
+ ListAppender eventAppender = null;
+ for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
+ if (entry.getKey().equals("events")) {
+ eventAppender = (ListAppender) ((AppenderAdapter.Adapter)
entry.getValue()).getAppender();
+ }
+ }
+ assertNotNull("No Event Appender", eventAppender);
+ List<LoggingEvent> events = eventAppender.getEvents();
+ assertTrue("No events", events != null && events.size() > 0);
+ assertNotNull("No properties in the event",
events.get(0).getProperties());
+ assertTrue("Key was not inserted",
events.get(0).getProperties().containsKey("hello"));
+ assertEquals("Key value is incorrect", "world",
events.get(0).getProperties().get("hello"));
+ }
+}
diff --git
a/log4j-1.2-api/src/test/java/org/apache/log4j/config/RewriteAppenderTest.java
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/RewriteAppenderTest.java
new file mode 100644
index 0000000..d7aca5c
--- /dev/null
+++
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/RewriteAppenderTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.log4j.config;
+
+import org.apache.log4j.ListAppender;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+import org.apache.log4j.bridge.AppenderAdapter;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test RewriteAppender
+ */
+public class RewriteAppenderTest {
+
+ @BeforeClass
+ public static void beforeClass() {
+
System.setProperty(ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY,
"target/test-classes/log4j1-rewrite.xml");
+ }
+
+ @After
+ public void after() {
+ ThreadContext.clearMap();
+ }
+
+ @Test
+ public void testRewrite() throws Exception {
+ Logger logger = LogManager.getLogger("test");
+ ThreadContext.put("key1", "This is a test");
+ ThreadContext.put("hello", "world");
+ logger.debug("Say hello");
+ LoggerContext context = (LoggerContext)
org.apache.logging.log4j.LogManager.getContext(false);
+ Configuration configuration = context.getConfiguration();
+ Map<String, Appender> appenders = configuration.getAppenders();
+ ListAppender eventAppender = null;
+ for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
+ if (entry.getKey().equals("events")) {
+ eventAppender = (ListAppender) ((AppenderAdapter.Adapter)
entry.getValue()).getAppender();
+ }
+ }
+ assertNotNull("No Event Appender", eventAppender);
+ List<LoggingEvent> events = eventAppender.getEvents();
+ assertTrue("No events", events != null && events.size() > 0);
+ assertNotNull("No properties in the event",
events.get(0).getProperties());
+ assertTrue("Key was not inserted",
events.get(0).getProperties().containsKey("key2"));
+ assertEquals("Key value is incorrect", "Log4j",
events.get(0).getProperties().get("key2"));
+ }
+}
diff --git a/log4j-1.2-api/src/test/resources/log4j1-maprewrite.xml
b/log4j-1.2-api/src/test/resources/log4j1-maprewrite.xml
new file mode 100644
index 0000000..19973f4
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/log4j1-maprewrite.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<!--<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="events" class="org.apache.log4j.ListAppender">
+ </appender>
+
+ <appender name="rewrite" class="org.apache.log4j.rewrite.RewriteAppender">
+ <appender-ref ref="events"/>
+ <rewritePolicy class="org.apache.log4j.rewrite.MapRewritePolicy">
+ </rewritePolicy>
+ </appender>
+
+ <root>
+ <priority value ="trace" />
+ <appender-ref ref="rewrite" />
+ </root>
+
+</log4j:configuration>
\ No newline at end of file
diff --git a/log4j-1.2-api/src/test/resources/log4j1-rewrite.xml
b/log4j-1.2-api/src/test/resources/log4j1-rewrite.xml
new file mode 100644
index 0000000..25eb1b5
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/log4j1-rewrite.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+<!--<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">-->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="events" class="org.apache.log4j.ListAppender">
+ </appender>
+
+ <appender name="rewrite" class="org.apache.log4j.rewrite.RewriteAppender">
+ <appender-ref ref="events"/>
+ <rewritePolicy class="org.apache.log4j.rewrite.PropertyRewritePolicy">
+ <param name="properties" value="key2=Log4j"/>
+ </rewritePolicy>
+ </appender>
+
+ <root>
+ <priority value ="trace" />
+ <appender-ref ref="rewrite" />
+ </root>
+
+</log4j:configuration>
\ No newline at end of file