001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.log4j.rewrite; 018 019import org.apache.log4j.bridge.LogEventAdapter; 020import org.apache.log4j.helpers.OptionConverter; 021import org.apache.log4j.spi.LocationInfo; 022import org.apache.log4j.spi.LoggingEvent; 023import org.apache.logging.log4j.core.LogEvent; 024import org.apache.logging.log4j.core.impl.Log4jLogEvent; 025import org.apache.logging.log4j.message.MapMessage; 026import org.apache.logging.log4j.message.Message; 027import org.apache.logging.log4j.message.SimpleMessage; 028import org.apache.logging.log4j.util.SortedArrayStringMap; 029 030import java.util.HashMap; 031import java.util.Map; 032 033/** 034 * This policy rewrites events where the message of the 035 * original event implements java.util.Map. 036 * All other events are passed through unmodified. 037 * If the map contains a "message" entry, the value will be 038 * used as the message for the rewritten event. The rewritten 039 * event will have a property set that is the combination of the 040 * original property set and the other members of the message map. 041 * If both the original property set and the message map 042 * contain the same entry, the value from the message map 043 * will overwrite the original property set. 044 * <p> 045 * The combination of the RewriteAppender and this policy 046 * performs the same actions as the MapFilter from log4j 1.3. 047 * </p> 048 */ 049public class MapRewritePolicy implements RewritePolicy { 050 /** 051 * {@inheritDoc} 052 */ 053 @Override 054 public LoggingEvent rewrite(final LoggingEvent source) { 055 Object msg = source.getMessage(); 056 if (msg instanceof MapMessage || msg instanceof Map) { 057 Map<String, String> props = source.getProperties() != null ? new HashMap<>(source.getProperties()) 058 : new HashMap<>(); 059 @SuppressWarnings("unchecked") 060 Map<String, Object> eventProps = msg instanceof Map ? (Map) msg : ((MapMessage) msg).getData(); 061 // 062 // if the map sent in the logging request 063 // has "message" entry, use that as the message body 064 // otherwise, use the entire map. 065 // 066 Message newMessage = null; 067 Object newMsg = eventProps.get("message"); 068 if (newMsg != null) { 069 newMessage = new SimpleMessage(newMsg.toString()); 070 for (Map.Entry<String, Object> entry : eventProps.entrySet()) { 071 if (!("message".equals(entry.getKey()))) { 072 props.put(entry.getKey(), entry.getValue().toString()); 073 } 074 } 075 } else { 076 return source; 077 } 078 079 LogEvent event; 080 if (source instanceof LogEventAdapter) { 081 event = new Log4jLogEvent.Builder(((LogEventAdapter) source).getEvent()) 082 .setMessage(newMessage) 083 .setContextData(new SortedArrayStringMap(props)) 084 .build(); 085 } else { 086 LocationInfo info = source.getLocationInformation(); 087 StackTraceElement element = new StackTraceElement(info.getClassName(), info.getMethodName(), 088 info.getFileName(), Integer.parseInt(info.getLineNumber())); 089 Thread thread = getThread(source.getThreadName()); 090 long threadId = thread != null ? thread.getId() : 0; 091 int threadPriority = thread != null ? thread.getPriority() : 0; 092 event = Log4jLogEvent.newBuilder() 093 .setContextData(new SortedArrayStringMap(props)) 094 .setLevel(OptionConverter.convertLevel(source.getLevel())) 095 .setLoggerFqcn(source.getFQNOfLoggerClass()) 096 .setMarker(null) 097 .setMessage(newMessage) 098 .setSource(element) 099 .setLoggerName(source.getLoggerName()) 100 .setThreadName(source.getThreadName()) 101 .setThreadId(threadId) 102 .setThreadPriority(threadPriority) 103 .setThrown(source.getThrowableInformation().getThrowable()) 104 .setTimeMillis(source.getTimeStamp()) 105 .setNanoTime(0) 106 .setThrownProxy(null) 107 .build(); 108 } 109 return new LogEventAdapter(event); 110 } 111 return source; 112 113 } 114 115 private Thread getThread(String name) { 116 for (Thread thread : Thread.getAllStackTraces().keySet()) { 117 if (thread.getName().equals(name)) { 118 return thread; 119 } 120 } 121 return null; 122 } 123}