View Javadoc

1   /*
2    * Copyright 2007-2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springbyexample.util.log;
18  
19  import java.beans.PropertyDescriptor;
20  import java.lang.reflect.Method;
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import org.springframework.beans.BeanUtils;
25  import org.springframework.beans.BeansException;
26  import org.springframework.beans.FatalBeanException;
27  import org.springframework.beans.factory.config.BeanPostProcessor;
28  import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
29  import org.springframework.core.Ordered;
30  import org.springframework.util.ReflectionUtils;
31  
32  /**
33   * <p>Injects loggers into new bean instances based on reflection.</p>
34   * 
35   * <p>Default logger factories configured are SLF4J, Apache Commons, 
36   * Log4J, and JDK 1.4 Logging.</p>
37   * 
38   * @author Tim Voet
39   * @author David Winterfeldt
40   */
41  public class LoggerBeanPostProcessor implements BeanPostProcessor, Ordered {
42  
43      protected Map<String, String> hLoggerFactories = new HashMap<String, String>();
44      
45      protected String methodName = null;
46  
47      /**
48       * Constructor
49       */
50      public LoggerBeanPostProcessor() {
51          hLoggerFactories.put("org.slf4j.Logger", "org.slf4j.LoggerFactory.getLogger");
52          hLoggerFactories.put("org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory.getLog");
53          hLoggerFactories.put("org.apache.log4j.Logger", "org.apache.log4j.Logger.getLogger");
54          hLoggerFactories.put("java.util.logging.Logger", "java.util.logging.Logger.getLogger");
55      }
56      
57      /**
58       * Sets target method name to set logger.
59       */
60      public void setMethodName(String methodName) {
61          this.methodName = methodName;
62      }
63      
64      /**
65       * Set logger factory <code>Map</code>.
66       */
67      public void setLoggerFactoryMap(Map<String, String> hLoggerFactories) {
68          this.hLoggerFactories = hLoggerFactories;
69      }
70  
71      /*
72       * This method is used to execute before a bean's initialization callback.
73       * 
74       * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
75       */
76      public Object postProcessBeforeInitialization(Object bean, String beanName) 
77              throws BeansException {
78          processLogger(bean, methodName);
79  
80          return bean;
81      }
82  
83      /**
84       * This method is used to execute after a bean's initialization callback.
85       * 
86       * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
87       */
88      public Object postProcessAfterInitialization(Object bean, String beanName)
89              throws BeansException {
90          return bean;
91      }
92  
93      /*
94       * Get order for processing.
95       * 
96       * @see org.springframework.core.Ordered#getOrder()
97       */
98      public int getOrder() {
99          return Ordered.HIGHEST_PRECEDENCE;
100     }
101 
102     /**
103      * Instantiates bean specific loggers and sets them.
104      */
105     protected void processLogger(final Object bean, final String methodName) {
106         final Class<?> clazz = bean.getClass();
107         
108         ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {
109             public void doWith(Method method) {
110                 if (method.getName().equals(methodName)) {
111                     try {
112                         injectMethod(bean, method);
113                     } catch (Throwable e) {
114                         throw new FatalBeanException("Problem injecting logger.  " + e.getMessage(), e);
115                     }
116                 }
117             }
118         });    
119     }
120     
121     /**
122      * Processes a property descriptor to inject a logger.
123      */
124     public void injectMethod(Object bean, Method method) {
125         PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
126         
127         if (pd != null) {
128             String canonicalName = pd.getPropertyType().getCanonicalName();
129 
130             Object logger = getLogger(bean.getClass().getName(), canonicalName);
131 
132             if (logger != null) {
133                 try {                                                       
134                     pd.getWriteMethod().invoke(bean, new Object[] { logger });
135                 } catch (Throwable e) {
136                     throw new FatalBeanException("Problem injecting logger.  " + e.getMessage(), e);
137                 }
138             }
139         }
140     }
141     
142     /**
143      * Gets logger based on the logger name and type of 
144      * logger (class name, ex: 'org.slf4j.Logger').
145      */
146     protected Object getLogger(String loggerName, String loggerType) {
147         Object result = null;
148         
149         String staticMethod = hLoggerFactories.get(loggerType);
150 
151         if (staticMethod != null) {
152             try {
153                 MethodInvokingFactoryBean factory = new MethodInvokingFactoryBean();
154                 factory.setStaticMethod(staticMethod);
155                 factory.setArguments(new Object[] { loggerName });
156                 factory.afterPropertiesSet();
157                 
158                 result = factory.getObject();
159             } catch (Throwable e) {
160                 throw new FatalBeanException("Problem injecting logger.  " + e.getMessage(), e);
161             }
162         }
163         
164         return result;
165     }
166     
167 }