001    /*****************************************************************************
002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     * Original code by Mauro Talevi                                             *
009     *****************************************************************************/
010    
011    package org.picocontainer.gems.monitors;
012    
013    import java.io.Serializable;
014    import java.lang.reflect.Constructor;
015    import java.lang.reflect.Method;
016    import java.lang.reflect.Member;
017    
018    import org.apache.commons.logging.Log;
019    import org.apache.commons.logging.LogFactory;
020    import org.picocontainer.ComponentMonitor;
021    import org.picocontainer.monitors.AbstractComponentMonitor;
022    import org.picocontainer.monitors.DefaultComponentMonitor;
023    
024    
025    /**
026     * A {@link ComponentMonitor} which writes to a Commons Logging {@link Log Log} instance.
027     * The Log instance can either be injected or, if not set, the {@link LogFactory LogFactory}
028     * will be used to retrieve it at every invocation of the monitor.
029     * 
030     * @author Paul Hammant
031     * @author Mauro Talevi
032     * @version $Revision: $
033     */
034    public class CommonsLoggingComponentMonitor extends AbstractComponentMonitor implements Serializable {
035    
036        private Log log;
037        private final ComponentMonitor delegate;
038    
039        /**
040         * Creates a CommonsLoggingComponentMonitor with no Log instance set.
041         * The {@link LogFactory LogFactory} will be used to retrieve the Log instance
042         * at every invocation of the monitor.
043         */
044        public CommonsLoggingComponentMonitor() {
045            delegate = new DefaultComponentMonitor();
046        }
047    
048        /**
049         * Creates a CommonsLoggingComponentMonitor with a given Log instance class.
050         * The class name is used to retrieve the Log instance.
051         * 
052         * @param logClass the class of the Log
053         */
054        public CommonsLoggingComponentMonitor(Class logClass) {
055            this(logClass.getName());
056        }
057    
058        /**
059         * Creates a CommonsLoggingComponentMonitor with a given Log instance name. It uses the
060         * {@link LogFactory LogFactory} to create the Log instance.
061         * 
062         * @param logName the name of the Log
063         */
064        public CommonsLoggingComponentMonitor(String logName) {
065            this(LogFactory.getLog(logName));
066        }
067    
068        /**
069         * Creates a CommonsLoggingComponentMonitor with a given Log instance
070         * 
071         * @param log the Log to write to
072         */
073        public CommonsLoggingComponentMonitor(Log log) {
074            this();
075            this.log = log;
076        }
077    
078        /**
079         * Creates a CommonsLoggingComponentMonitor with a given Log instance class.
080         * The class name is used to retrieve the Log instance.
081         *
082         * @param logClass the class of the Log
083         */
084        public CommonsLoggingComponentMonitor(Class logClass, ComponentMonitor delegate) {
085            this(logClass.getName(), delegate);
086        }
087    
088        /**
089         * Creates a CommonsLoggingComponentMonitor with a given Log instance name. It uses the
090         * {@link LogFactory LogFactory} to create the Log instance.
091         *
092         * @param logName the name of the Log
093         */
094        public CommonsLoggingComponentMonitor(String logName, ComponentMonitor delegate) {
095            this(LogFactory.getLog(logName), delegate);
096        }
097    
098        /**
099         * Creates a CommonsLoggingComponentMonitor with a given Log instance
100         *
101         * @param log the Log to write to
102         */
103        public CommonsLoggingComponentMonitor(Log log, ComponentMonitor delegate) {
104            this.log = log;
105            this.delegate = delegate;
106        }
107    
108    
109        public void instantiating(Constructor constructor) {
110            Log log = getLog(constructor);
111            if (log.isDebugEnabled()) {
112                log.debug(format(INSTANTIATING, new Object[]{toString(constructor)}));
113            }
114            delegate.instantiating(constructor);
115        }
116    
117        public void instantiated(Constructor constructor, long duration) {
118            Log log = getLog(constructor);
119            if (log.isDebugEnabled()) {
120                log.debug(format(INSTANTIATED, new Object[]{toString(constructor), new Long(duration)}));
121            }
122            delegate.instantiated(constructor, duration);
123        }
124    
125        public void instantiated(Constructor constructor, Object instantiated, Object[] parameters, long duration) {
126            Log log = getLog(constructor);
127            if (log.isDebugEnabled()) {
128                log.debug(format(INSTANTIATED2, new Object[]{toString(constructor), new Long(duration), instantiated.getClass().getName(), toString(parameters)}));
129            }
130            delegate.instantiated(constructor, instantiated, parameters, duration);
131        }
132    
133        public void instantiationFailed(Constructor constructor, Exception cause) {
134            Log log = getLog(constructor);
135            if (log.isWarnEnabled()) {
136                log.warn(format(INSTANTIATION_FAILED, new Object[]{toString(constructor), cause.getMessage()}), cause);
137            }
138            delegate.instantiationFailed(constructor, cause);
139        }
140    
141        public void invoking(Method method, Object instance) {
142            Log log = getLog(method);
143            if (log.isDebugEnabled()) {
144                log.debug(format(INVOKING, new Object[]{toString(method), instance}));
145            }
146            delegate.invoking(method, instance);
147        }
148    
149        public void invoked(Method method, Object instance, long duration) {
150            Log log = getLog(method);
151            if (log.isDebugEnabled()) {
152                log.debug(format(INVOKED, new Object[]{toString(method), instance, new Long(duration)}));
153            }
154            delegate.invoked(method, instance,  duration);
155        }
156    
157        public void invocationFailed(Method method, Object instance, Exception cause) {
158            Log log = getLog(method);
159            if (log.isWarnEnabled()) {
160                log.warn(format(INVOCATION_FAILED, new Object[]{toString(method), instance, cause.getMessage()}), cause);
161            }
162            delegate.invocationFailed(method, instance, cause);
163        }
164    
165        public void lifecycleInvocationFailed(Method method, Object instance, RuntimeException cause) {
166            Log log = getLog(method);
167            if (log.isWarnEnabled()) {
168                log.warn(format(LIFECYCLE_INVOCATION_FAILED, new Object[]{toString(method), instance, cause.getMessage()}), cause);
169            }
170            delegate.lifecycleInvocationFailed(method, instance, cause);
171        }
172    
173        protected Log getLog(Member member) {
174            if ( log != null ){
175                return log;
176            } 
177            return LogFactory.getLog(member.getDeclaringClass());
178        }
179    
180    }