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 java.beans.Introspector;
020import java.beans.PropertyDescriptor;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.apache.log4j.Logger;
025import org.apache.log4j.helpers.LogLog;
026import org.apache.log4j.spi.LoggingEvent;
027
028/**
029 * This policy rewrites events by evaluating any
030 * JavaBean properties on the message object and adding them
031 * to the event properties.  If the message object has a
032 * message property, the value of that property will be
033 * used as the message for the rewritten event and will
034 * not be added to the event properties.  Values from the
035 * JavaBean properties will replace any existing property
036 * with the same name.
037 *
038 * The combination of the RewriteAppender and this policy
039 * performs the same actions as the ReflectionFilter from log4j 1.3. 
040 */
041public class ReflectionRewritePolicy implements RewritePolicy {
042    /**
043     * {@inheritDoc}
044     */
045    public LoggingEvent rewrite(final LoggingEvent source) {
046        Object msg = source.getMessage();
047        if (!(msg instanceof String)) {
048            Object newMsg = msg;
049            Map rewriteProps = new HashMap(source.getProperties());
050
051            try {
052                PropertyDescriptor[] props = Introspector.getBeanInfo(
053                        msg.getClass(), Object.class).getPropertyDescriptors();
054                if (props.length > 0) {
055                    for (int i=0;i<props.length;i++) {
056                        try {
057                            Object propertyValue =
058                                props[i].getReadMethod().invoke(msg,
059                                        (Object[]) null);
060                            if ("message".equalsIgnoreCase(props[i].getName())) {
061                                newMsg = propertyValue;
062                            } else {
063                                rewriteProps.put(props[i].getName(), propertyValue);
064                            }
065                        } catch (Exception e) {
066                            LogLog.warn("Unable to evaluate property " +
067                                    props[i].getName(), e);
068                        }
069                    }
070                    return new LoggingEvent(
071                            source.getFQNOfLoggerClass(),
072                            source.getLogger() != null ? source.getLogger(): Logger.getLogger(source.getLoggerName()),
073                            source.getTimeStamp(),
074                            source.getLevel(),
075                            newMsg,
076                            source.getThreadName(),
077                            source.getThrowableInformation(),
078                            source.getNDC(),
079                            source.getLocationInformation(),
080                            rewriteProps);
081                }
082            } catch (Exception e) {
083                LogLog.warn("Unable to get property descriptors", e);
084            }
085
086        }
087        return source;
088    }
089}