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