    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 static org.picocontainer.monitors.ComponentMonitorHelper.ctorToString;
    014    import static org.picocontainer.monitors.ComponentMonitorHelper.memberToString;
    015    import static org.picocontainer.monitors.ComponentMonitorHelper.methodToString;
    016    import static org.picocontainer.monitors.ComponentMonitorHelper.parmsToString;
    017
    018    import java.io.Serializable;
    019    import java.lang.reflect.Constructor;
    020    import java.lang.reflect.Member;
    021    import java.lang.reflect.Method;
    022
    023    import org.apache.commons.logging.Log;
    024    import org.apache.commons.logging.LogFactory;
    025    import org.picocontainer.ComponentAdapter;
    026    import org.picocontainer.ComponentMonitor;
    027    import org.picocontainer.MutablePicoContainer;
    028    import org.picocontainer.PicoContainer;
    029    import org.picocontainer.Injector;
    030    import org.picocontainer.Behavior;
    031    import org.picocontainer.monitors.ComponentMonitorHelper;
    032    import org.picocontainer.monitors.NullComponentMonitor;
    033
    034
    035    /**
    036     * A {@link ComponentMonitor} which writes to a Commons Logging {@link Log Log} instance.
    037     * The Log instance can either be injected or, if not set, the {@link LogFactory LogFactory}
    038     * will be used to retrieve it at every invocation of the monitor.
    039     * <h4>Note on Serialization</h4>
    040     * <p>Commons Logging does <em>not</em> guarantee Serialization.  It is supported when using Log4j
    041     * as a back end, but you should write a test case to determine if your particular logger implementation
    042     * is supported if you plan on serializing this ComponentMonitor.</p>
    043     *
    044     * @author Paul Hammant
    045     * @author Mauro Talevi
    046     */
    047    @SuppressWarnings("serial")
    048    public class CommonsLoggingComponentMonitor implements ComponentMonitor, Serializable {
    049
    050
    051            /**
    052             * Commons Logger.
    053             */
    054            private Log log;
    055
    056
    057            /**
    058             * Delegate for component monitor chains.
    059             */
    060        private final ComponentMonitor delegate;
    061
    062        /**
    063         * Creates a CommonsLoggingComponentMonitor with no Log instance set.
    064         * The {@link LogFactory LogFactory} will be used to retrieve the Log instance
    065         * at every invocation of the monitor.
    066         */
    067        public CommonsLoggingComponentMonitor() {
    068            delegate = new NullComponentMonitor();
    069        }
    070
    071        /**
    072         * Creates a CommonsLoggingComponentMonitor with a given Log instance class.
    073         * The class name is used to retrieve the Log instance.
    074         *
    075         * @param logClass the class of the Log
    076         */
    077        public CommonsLoggingComponentMonitor(final Class<?> logClass) {
    078            this(logClass.getName());
    079        }
    080
    081        /**
    082         * Creates a CommonsLoggingComponentMonitor with a given Log instance name. It uses the
    083         * {@link LogFactory LogFactory} to create the Log instance.
    084         *
    085         * @param logName the name of the Log
    086         */
    087        public CommonsLoggingComponentMonitor(final String logName) {
    088            this(LogFactory.getLog(logName));
    089        }
    090
    091        /**
    092         * Creates a CommonsLoggingComponentMonitor with a given Log instance
    093         * @param log the Log to write to
    094         */
    095        public CommonsLoggingComponentMonitor(final Log log) {
    096            this();
    097            this.log = log;
    098        }
    099
    100        /**
    101         * Creates a CommonsLoggingComponentMonitor with a given Log instance class.
    102         * The class name is used to retrieve the Log instance.
    103         *
    104         * @param logClass the class of the Log
    105         * @param delegate the delegate
    106         */
    107        public CommonsLoggingComponentMonitor(final Class<?> logClass, final ComponentMonitor delegate) {
    108            this(logClass.getName(), delegate);
    109        }
    110
    111        /**
    112         * Creates a CommonsLoggingComponentMonitor with a given Log instance name. It uses the
    113         * {@link LogFactory LogFactory} to create the Log instance.
    114         *
    115         * @param logName the name of the Log
    116         * @param delegate the delegate
    117         */
    118        public CommonsLoggingComponentMonitor(final String logName, final ComponentMonitor delegate) {
    119            this(LogFactory.getLog(logName), delegate);
    120        }
    121
    122        /**
    123         * Creates a CommonsLoggingComponentMonitor with a given Log instance.
    124         * @param log the Log with which to write events.
    125         * @param delegate the delegate
    126         */
    127        public CommonsLoggingComponentMonitor(final Log log, final ComponentMonitor delegate) {
    128            this.log = log;
    129            this.delegate = delegate;
    130        }
    131
    132
    133        /** {@inheritDoc} **/
    134       public <T> Constructor<T> instantiating(final PicoContainer container, final ComponentAdapter<T> componentAdapter,
    135                                         final Constructor<T> constructor
    136        ) {
    137            Log log = getLog(constructor);
    138            if (log.isDebugEnabled()) {
    139                log.debug(ComponentMonitorHelper.format(ComponentMonitorHelper.INSTANTIATING, ctorToString(constructor)));
    140            }
    141            return delegate.instantiating(container, componentAdapter, constructor);
    142        }
    143
    144       /** {@inheritDoc} **/
    145        public <T> void instantiated(final PicoContainer container, final ComponentAdapter<T> componentAdapter,
    146                                 final Constructor<T> constructor,
    147                                 final Object instantiated,
    148                                 final Object[] parameters,
    149                                 final long duration) {
    150            Log log = getLog(constructor);
    151            if (log.isDebugEnabled()) {
    152                log.debug(ComponentMonitorHelper.format(ComponentMonitorHelper.INSTANTIATED, ctorToString(constructor), duration, instantiated.getClass().getName(), parmsToString(parameters)));
    153            }
    154            delegate.instantiated(container, componentAdapter, constructor, instantiated, parameters, duration);
    155        }
    156
    157        /** {@inheritDoc} **/
    158        public <T> void instantiationFailed(final PicoContainer container,
    159                                        final ComponentAdapter<T>  componentAdapter,
    160                                        final Constructor<T>  constructor,
    161                                        final Exception cause) {
    162            Log log = getLog(constructor);
    163            if (log.isWarnEnabled()) {
    164                log.warn(ComponentMonitorHelper.format(ComponentMonitorHelper.INSTANTIATION_FAILED, ctorToString(constructor), cause.getMessage()), cause);
    165            }
    166            delegate.instantiationFailed(container, componentAdapter, constructor, cause);
    167        }
    168
    169        /** {@inheritDoc} **/
    170        public Object invoking(final PicoContainer container,
    171                             final ComponentAdapter<?> componentAdapter,
    172                             final Member member,
    173                             final Object instance,
    174                             final Object[] args) {
    175            Log log = getLog(member);
    176            if (log.isDebugEnabled()) {
    177                log.debug(ComponentMonitorHelper.format(ComponentMonitorHelper.INVOKING, memberToString(member), instance));
    178            }
    179            return delegate.invoking(container, componentAdapter, member, instance, args);
    180        }
    181
    182        /** {@inheritDoc} **/
    183        public void invoked(final PicoContainer container,
    184                            final ComponentAdapter<?> componentAdapter,
    185                            final Member member,
    186                            final Object instance,
    187                            final long duration,
    188                            final Object[] args,
    189                            final Object retVal) {
    190            Log log = getLog(member);
    191            if (log.isDebugEnabled()) {
    192                log.debug(ComponentMonitorHelper.format(ComponentMonitorHelper.INVOKED, methodToString(member), instance, duration));
    193            }
    194            delegate.invoked(container, componentAdapter, member, instance,  duration, args, retVal);
    195        }
    196
    197        /** {@inheritDoc} **/
    198        public void invocationFailed(final Member member, final Object instance, final Exception cause) {
    199            Log log = getLog(member);
    200            if (log.isWarnEnabled()) {
    201                log.warn(ComponentMonitorHelper.format(ComponentMonitorHelper.INVOCATION_FAILED, memberToString(member), instance, cause.getMessage()), cause);
    202            }
    203            delegate.invocationFailed(member, instance, cause);
    204        }
    205
    206        /** {@inheritDoc} **/
    207        public void lifecycleInvocationFailed(final MutablePicoContainer container,
    208                                              final ComponentAdapter<?> componentAdapter, final Method method,
    209                                              final Object instance,
    210                                              final RuntimeException cause) {
    211            Log log = getLog(method);
    212            if (log.isWarnEnabled()) {
    213                log.warn(ComponentMonitorHelper.format(ComponentMonitorHelper.LIFECYCLE_INVOCATION_FAILED, methodToString(method), instance, cause.getMessage()), cause);
    214            }
    215            delegate.lifecycleInvocationFailed(container, componentAdapter, method, instance, cause);
    216        }
    217
    218        /** {@inheritDoc} **/
    219        public Object noComponentFound(final MutablePicoContainer container, final Object componentKey) {
    220            Log log = this.log != null ? this.log : LogFactory.getLog(ComponentMonitor.class);
    221            if (log.isWarnEnabled()) {
    222                log.warn(ComponentMonitorHelper.format(ComponentMonitorHelper.NO_COMPONENT, componentKey));
    223            }
    224            return delegate.noComponentFound(container, componentKey);
    225        }
    226
    227        /** {@inheritDoc} **/
    228        public Injector newInjector(final Injector injector) {
    229            return delegate.newInjector(injector);
    230        }
    231
    232        /** {@inheritDoc} **/
    233        public Behavior newBehavior(Behavior behavior) {
    234            return delegate.newBehavior(behavior);
    235        }
    236
    237        /**
    238         * Retrieves the logger appropriate for the calling member's class.
    239         * @param member constructor/method/field who's callback is required.
    240         * @return the Commons logging instance.
    241         */
    242        protected Log getLog(final Member member) {
    243            if ( log != null ){
    244                return log;
    245            }
    246            return LogFactory.getLog(member.getDeclaringClass());
    247        }
    248
    249
    250    }