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