    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 Centerline Computers, Inc.                               *
    009     *****************************************************************************/
    010
    011    package org.picocontainer.gems.containers;
    012
    013    import org.picocontainer.ComponentAdapter;
    014    import org.picocontainer.MutablePicoContainer;
    015    import org.picocontainer.Parameter;
    016    import org.picocontainer.PicoContainer;
    017    import org.picocontainer.PicoVisitor;
    018    import org.picocontainer.NameBinding;
    019    import org.picocontainer.lifecycle.LifecycleState;
    020
    021    import java.io.ObjectInputStream;
    022    import java.io.ObjectOutputStream;
    023    import java.io.Serializable;
    024    import java.util.Collection;
    025    import java.util.List;
    026    import java.util.Properties;
    027    import java.lang.annotation.Annotation;
    028    import java.lang.reflect.Type;
    029
    030    import org.apache.log4j.Logger;
    031
    032    /**
    033     * Decorates a MutablePicoContainer to provide extensive tracing capabilities
    034     * for all function calls into the Picocontainers.
    035     * <p>
    036     * By default, this class uses <tt>org.picocontainer.PicoContainer</tt> as its
    037     * logging category, however, this may be changed by providing the logger in its
    038     * alternate constructor.
    039     * </p>
    040     * <p>
    041     * Start and Stop events are logged under <tt>info</tt> priority, as are all
    042     * conditions where querying for an object returns a null object (e.g.,
    043     * getComponentAdapter(Object) returns null). All other functions use
    044     * <tt>debug</tt> priority.
    045     * </p>
    046     * <p>
    047     * If used in nanocontainer, you can add wrap your PicoContainer with the
    048     * Log4jTracingContainerDecorator: (Groovy Example)
    049     * </p>
    050     *
    051     * <pre>
    052     *              pico = builder.container(parent: parent) {
    053     *                      //addComponent(.....)
    054     *                      //And others.
    055     *              }
    056     *
    057     *              //Wrap the underlying NanoContainer with a Decorated Pico.
    058     *              pico = new org.picocontainer.gems.containers.Log4jTracingContainerDecorator (pico.getPico())
    059     * </pre>
    060     *
    061     * @author Michael Rimov
    062     * @deprecated Since PicoContainer 2.3,  Pico 2 ComponentAdapters can now do everything that this
    063     * decorator provided.
    064     */
    065    @Deprecated
    066    @SuppressWarnings("serial")
    067    public class Log4jTracingContainerDecorator implements MutablePicoContainer, Serializable {
    068
    069
    070            /** Wrapped container. */
    071        private final MutablePicoContainer delegate;
    072
    073        /** Logger instance used for writing events. */
    074        private transient Logger logger;
    075
    076        /**
    077         * Default typical wrapper that wraps another MutablePicoContainer.
    078         *
    079         * @param delegate Container to be decorated.
    080         *
    081         * @throws NullPointerException if delegate is null.
    082         */
    083        public Log4jTracingContainerDecorator(final MutablePicoContainer delegate) {
    084            this(delegate, Logger.getLogger(PicoContainer.class));
    085        }
    086
    087        /**
    088         * Alternate constructor that allows specification of the Logger to use.
    089         *
    090         * @param delegate Container to be decorated.
    091         * @param logger   specific Log4j Logger to use.
    092         *
    093         * @throws NullPointerException if delegate or logger is null.
    094         */
    095        public Log4jTracingContainerDecorator(final MutablePicoContainer delegate, final Logger logger) {
    096            if (delegate == null) {
    097                throw new NullPointerException("delegate");
    098            }
    099
    100            if (logger == null) {
    101                throw new NullPointerException("logger");
    102            }
    103
    104            this.delegate = delegate;
    105            this.logger = logger;
    106        }
    107
    108        /**
    109         * Standard message handling for cases when a null object is returned for a
    110         * given key.
    111         *
    112         * @param componentKeyOrType Component key that does not exist
    113         * @param target       Logger to log into
    114         */
    115        protected void onKeyOrTypeDoesNotExistInContainer(final Object componentKeyOrType, final Logger target) {
    116            String s =
    117                componentKeyOrType instanceof Class ? ((Class)componentKeyOrType).getName() : (String)componentKeyOrType;
    118            logger.info("Could not find component " + s
    119                        + " in container or parent container.");
    120        }
    121
    122        /**
    123         * {@inheritDoc}
    124         *
    125         * @param visitor
    126         *
    127         * @see org.picocontainer.PicoContainer#accept(org.picocontainer.PicoVisitor)
    128         */
    129        public void accept(final PicoVisitor visitor) {
    130            if (logger.isDebugEnabled()) {
    131                logger.debug("Visiting Container " + delegate + " with visitor " + visitor);
    132            }
    133            delegate.accept(visitor);
    134        }
    135
    136        /**
    137         * {@inheritDoc}
    138         *
    139         * @param child
    140         *
    141         * @return
    142         *
    143         * @see org.picocontainer.MutablePicoContainer#addChildContainer(org.picocontainer.PicoContainer)
    144         */
    145        public MutablePicoContainer addChildContainer(final PicoContainer child) {
    146            if (logger.isDebugEnabled()) {
    147                logger.debug("Adding child container: " + child + " to container " + delegate);
    148            }
    149            return delegate.addChildContainer(child);
    150        }
    151
    152        /**
    153         * {@inheritDoc}
    154         *
    155         * @see org.picocontainer.Disposable#dispose()
    156         */
    157        public void dispose() {
    158            if (logger.isDebugEnabled()) {
    159                logger.debug("Disposing container " + delegate);
    160            }
    161            delegate.dispose();
    162        }
    163
    164        /**
    165         * {@inheritDoc}
    166         *
    167         * @param componentKey
    168         *
    169         * @return
    170         *
    171         * @see org.picocontainer.PicoContainer#getComponentAdapter(java.lang.Object)
    172         */
    173        public ComponentAdapter<?> getComponentAdapter(final Object componentKey) {
    174            if (logger.isDebugEnabled()) {
    175                logger.debug("Locating component adapter with key " + componentKey);
    176            }
    177
    178            ComponentAdapter adapter = delegate.getComponentAdapter(componentKey);
    179            if (adapter == null) {
    180                onKeyOrTypeDoesNotExistInContainer(componentKey, logger);
    181            }
    182            return adapter;
    183        }
    184
    185        /**
    186         * {@inheritDoc}
    187         *
    188         * @param componentType
    189         *
    190         * @return ComponentAdapter or null.
    191         *
    192         * @see org.picocontainer.PicoContainer#getComponentAdapter(java.lang.Class)
    193         */
    194
    195        public <T> ComponentAdapter<T> getComponentAdapter(final Class<T> componentType, final NameBinding componentNameBinding) {
    196            if (logger.isDebugEnabled()) {
    197                logger.debug("Locating component adapter with type " + componentType);
    198            }
    199
    200            ComponentAdapter<T> ca = delegate.getComponentAdapter(componentType, componentNameBinding);
    201
    202            if (ca == null) {
    203                onKeyOrTypeDoesNotExistInContainer(ca, logger);
    204            }
    205            return ca;
    206        }
    207
    208        /**
    209         * {@inheritDoc}
    210         *
    211         * @return Collection or null.
    212         *
    213         * @see org.picocontainer.PicoContainer#getComponentAdapters()
    214         */
    215        public Collection<ComponentAdapter<?>> getComponentAdapters() {
    216            if (logger.isDebugEnabled()) {
    217                logger.debug("Grabbing all component adapters for container: " + delegate);
    218            }
    219            return delegate.getComponentAdapters();
    220        }
    221
    222        /**
    223         * {@inheritDoc}
    224         *
    225         * @param componentType
    226         *
    227         * @return List of ComponentAdapters
    228         *
    229         * @see org.picocontainer.PicoContainer#getComponentAdapters(java.lang.Class)
    230         */
    231        public <T> List<ComponentAdapter<T>> getComponentAdapters(final Class<T> componentType) {
    232            if (logger.isDebugEnabled()) {
    233                logger.debug("Grabbing all component adapters for container: " + delegate + " of type: "
    234                             + componentType.getName());
    235            }
    236            return delegate.getComponentAdapters(componentType);
    237        }
    238
    239        public <T> List<ComponentAdapter<T>> getComponentAdapters(final Class<T> componentType, final Class<? extends Annotation> binding) {
    240            if (logger.isDebugEnabled()) {
    241                logger.debug("Grabbing all component adapters for container: " + delegate + " of type: "
    242                             + componentType.getName() + ", binding:" + binding.getName());
    243            }
    244            return delegate.getComponentAdapters(componentType, binding);
    245        }
    246
    247        public <T> ComponentAdapter<T> getComponentAdapter(final Class<T> componentType, final Class<? extends Annotation> binding) {
    248            if (logger.isDebugEnabled()) {
    249                logger.debug("Grabbing component adapter for container: " + delegate + " of type: "
    250                             + componentType.getName() + ", binding:" + binding.getName());
    251            }
    252            return delegate.getComponentAdapter(componentType, binding);
    253        }
    254
    255        /**
    256         * {@inheritDoc}
    257         *
    258         * @param componentKeyOrType
    259         *
    260         * @return
    261         *
    262         * @see org.picocontainer.PicoContainer#getComponent(java.lang.Object)
    263         */
    264        public Object getComponent(final Object componentKeyOrType) {
    265
    266            if (logger.isDebugEnabled()) {
    267                logger.debug("Attempting to load component instance with "
    268                             + (componentKeyOrType instanceof Class ? "type" : "key")
    269                             + ": "
    270                             + (componentKeyOrType instanceof Class
    271                                ? ((Class)componentKeyOrType).getName()
    272                                : componentKeyOrType)
    273                             + " for container "
    274                             + delegate);
    275
    276            }
    277
    278            Object result = delegate.getComponent(componentKeyOrType);
    279            if (result == null) {
    280                onKeyOrTypeDoesNotExistInContainer(componentKeyOrType, logger);
    281            }
    282
    283            return result;
    284        }
    285
    286        public Object getComponent(final Object componentKeyOrType, final Type into) {
    287            if (logger.isDebugEnabled()) {
    288                logger.debug("Attempting to load component instance with "
    289                             + (componentKeyOrType instanceof Class ? "type" : "key")
    290                             + ": "
    291                             + (componentKeyOrType instanceof Class
    292                                ? ((Class)componentKeyOrType).getName()
    293                                : componentKeyOrType)
    294                             + " for container "
    295                             + delegate);
    296
    297            }
    298            Object result = delegate.getComponent(componentKeyOrType, into);
    299            if (result == null) {
    300                onKeyOrTypeDoesNotExistInContainer(componentKeyOrType, logger);
    301            }
    302
    303            return result;
    304        }
    305
    306        public <T> T getComponent(final Class<T> componentType) {
    307            return componentType.cast(getComponent((Object)componentType));
    308        }
    309
    310        public <T> T getComponent(final Class<T> componentType, final Class<? extends Annotation> binding) {
    311            if (logger.isDebugEnabled()) {
    312                logger.debug("Attempting to load component instance with "
    313                             + "type"
    314                             + ": "
    315                             + componentType.getName()
    316                             + " for container "
    317                             + delegate);
    318
    319            }
    320            return delegate.getComponent(componentType, binding);
    321        }
    322
    323        /**
    324         * {@inheritDoc}
    325         *
    326         * @param componentType
    327         * @return
    328         * @see org.picocontainer.PicoContainer#getComponent(java.lang.Class)
    329         */
    330    //      public Object getComponent(final Class componentType) {
    331    //              if (logger.isDebugEnabled()) {
    332    //                      logger.debug("Attempting to load component instance with type: " + componentType + " for container "
    333    //                                      + delegate);
    334    //
    335    //              }
    336    //
    337    //              Object result = delegate.getComponent(componentType);
    338    //              if (result == null) {
    339    //                      if (logger.isInfoEnabled()) {
    340    //                              logger.info("No component of type " + componentType.getName() + " was found in container: " + delegate);
    341    //                      }
    342    //              }
    343    //
    344    //              return result;
    345    //      }
    346
    347        /**
    348         * {@inheritDoc}
    349         *
    350         * @return
    351         *
    352         * @see org.picocontainer.PicoContainer#getComponents()
    353         */
    354        public List getComponents() {
    355            if (logger.isDebugEnabled()) {
    356                logger.debug("Retrieving all component instances for container " + delegate);
    357            }
    358            return delegate.getComponents();
    359        }
    360
    361        /**
    362         * {@inheritDoc}
    363         *
    364         * @param componentType
    365         *
    366         * @return
    367         *
    368         * @see org.picocontainer.PicoContainer#getComponents(java.lang.Class)
    369         */
    370        public <T> List<T> getComponents(final Class<T> componentType) {
    371            if (logger.isDebugEnabled()) {
    372                logger.debug("Loading all component instances of type " + componentType + " for container " + delegate);
    373            }
    374            List<T> result = delegate.getComponents(componentType);
    375            if (result == null || result.isEmpty()) {
    376                if (logger.isInfoEnabled()) {
    377                    logger.info("Could not find any components  " + " in container or parent container.");
    378                }
    379            }
    380
    381            return result;
    382        }
    383
    384        /**
    385         * {@inheritDoc}
    386         *
    387         * @return
    388         *
    389         * @see org.picocontainer.PicoContainer#getParent()
    390         */
    391        public PicoContainer getParent() {
    392            if (logger.isDebugEnabled()) {
    393                logger.debug("Retrieving the parent for container " + delegate);
    394            }
    395
    396            return delegate.getParent();
    397        }
    398
    399        /**
    400         * {@inheritDoc}
    401         *
    402         * @return
    403         *
    404         * @see org.picocontainer.MutablePicoContainer#makeChildContainer()
    405         */
    406        public MutablePicoContainer makeChildContainer() {
    407            if (logger.isDebugEnabled()) {
    408                logger.debug("Making child container for container " + delegate);
    409            }
    410
    411            // Wrap the new delegate
    412            return new Log4jTracingContainerDecorator(delegate.makeChildContainer());
    413        }
    414
    415        /**
    416         * {@inheritDoc}
    417         *
    418         * @param componentAdapter
    419         *
    420         * @return
    421         *
    422         * @see org.picocontainer.MutablePicoContainer#addAdapter(org.picocontainer.ComponentAdapter)
    423         */
    424        public MutablePicoContainer addAdapter(final ComponentAdapter componentAdapter) {
    425            if (logger.isDebugEnabled()) {
    426                logger.debug("Registering component adapter " + componentAdapter);
    427            }
    428
    429            return delegate.addAdapter(componentAdapter);
    430        }
    431
    432        /**
    433         * {@inheritDoc}
    434         *
    435         * @param componentKey
    436         * @param componentImplementationOrInstance
    437         *
    438         * @param parameters
    439         *
    440         * @return
    441         */
    442        public MutablePicoContainer addComponent(final Object componentKey,
    443                                                 final Object componentImplementationOrInstance,
    444                                                 final Parameter... parameters)
    445        {
    446
    447            if (logger.isDebugEnabled()) {
    448                logger.debug("Registering component "
    449                             + (componentImplementationOrInstance instanceof Class ? "implementation" : "instance")
    450                             + " with key " + componentKey + " and implementation "
    451                             + (componentImplementationOrInstance instanceof Class
    452                                ? ((Class)componentImplementationOrInstance).getCanonicalName()
    453                                : componentKey.getClass()) + " using parameters " + parameters);
    454            }
    455
    456            return delegate.addComponent(componentKey, componentImplementationOrInstance, parameters);
    457        }
    458
    459        /**
    460         * {@inheritDoc}
    461         *
    462         * @param implOrInstance
    463         *
    464         * @return
    465         *
    466         * @see org.picocontainer.MutablePicoContainer#addComponent(java.lang.Object)
    467         */
    468        public MutablePicoContainer addComponent(final Object implOrInstance) {
    469            if (logger.isDebugEnabled()) {
    470                logger.debug("Registering component impl or instance " + implOrInstance + "(class: "
    471                             + ((implOrInstance != null) ? implOrInstance.getClass().getName() : " null "));
    472            }
    473
    474            return delegate.addComponent(implOrInstance);
    475        }
    476
    477        public MutablePicoContainer addConfig(final String name, final Object val) {
    478            if (logger.isDebugEnabled()) {
    479                logger.debug("Registering config: " + name);
    480            }
    481
    482            return delegate.addConfig(name, val);
    483
    484        }
    485
    486        /**
    487         * {@inheritDoc}
    488         *
    489         * @param child
    490         *
    491         * @return
    492         *
    493         * @see org.picocontainer.MutablePicoContainer#removeChildContainer(org.picocontainer.PicoContainer)
    494         */
    495        public boolean removeChildContainer(final PicoContainer child) {
    496            if (logger.isDebugEnabled()) {
    497                logger.debug("Removing child container: " + child + " from parent: " + delegate);
    498            }
    499            return delegate.removeChildContainer(child);
    500        }
    501
    502        /**
    503         * {@inheritDoc}
    504         *
    505         * @see org.picocontainer.Startable#start()
    506         */
    507        public void start() {
    508            if (logger.isInfoEnabled()) {
    509                logger.info("Starting Container " + delegate);
    510            }
    511
    512            delegate.start();
    513        }
    514
    515        /**
    516         * {@inheritDoc}
    517         *
    518         * @see org.picocontainer.Startable#stop()
    519         */
    520        public void stop() {
    521            if (logger.isInfoEnabled()) {
    522                logger.info("Stopping Container " + delegate);
    523            }
    524            delegate.stop();
    525        }
    526
    527        /**
    528         * {@inheritDoc}
    529         *
    530         * @param componentKey
    531         *
    532         * @return
    533         *
    534         * @see org.picocontainer.MutablePicoContainer#removeComponent(java.lang.Object)
    535         */
    536        public ComponentAdapter removeComponent(final Object componentKey) {
    537            if (logger.isDebugEnabled()) {
    538                logger.debug("Unregistering component " + componentKey + " from container " + delegate);
    539            }
    540
    541            return delegate.removeComponent(componentKey);
    542        }
    543
    544        /**
    545         * {@inheritDoc}
    546         *
    547         * @param componentInstance
    548         *
    549         * @return
    550         *
    551         * @see org.picocontainer.MutablePicoContainer#removeComponentByInstance(java.lang.Object)
    552         */
    553        public ComponentAdapter removeComponentByInstance(final Object componentInstance) {
    554            if (logger.isDebugEnabled()) {
    555                logger.debug("Unregistering component by instance (" + componentInstance + ") from container " + delegate);
    556            }
    557
    558            return delegate.removeComponentByInstance(componentInstance);
    559        }
    560
    561        /**
    562         * Retrieves the logger instance used by this decorator.
    563         *
    564         * @return Logger instance.
    565         */
    566        public Logger getLoggerUsed() {
    567            return this.logger;
    568        }
    569
    570        private void readObject(final ObjectInputStream s) throws java.io.IOException, java.lang.ClassNotFoundException {
    571
    572            s.defaultReadObject();
    573            String loggerName = s.readUTF();
    574            logger = Logger.getLogger(loggerName);
    575        }
    576
    577        private void writeObject(final ObjectOutputStream s) throws java.io.IOException {
    578            s.defaultWriteObject();
    579            s.writeUTF(logger.getName());
    580        }
    581
    582        public MutablePicoContainer change(final Properties... properties) {
    583            return delegate.change(properties);
    584        }
    585
    586        public MutablePicoContainer as(final Properties... properties) {
    587            return delegate.as(properties);
    588        }
    589
    590        public void setName(String name) {
    591            delegate.setName(name);
    592        }
    593
    594        public void setLifecycleState(LifecycleState lifecycleState) {
    595            delegate.setLifecycleState(lifecycleState);
    596        }
    597    }