001    package org.picocontainer.gems.containers;
002    
003    import java.util.Collection;
004    import java.util.List;
005    
006    import org.apache.commons.logging.Log;
007    import org.apache.commons.logging.LogFactory;
008    import org.picocontainer.ComponentAdapter;
009    import org.picocontainer.MutablePicoContainer;
010    import org.picocontainer.Parameter;
011    import org.picocontainer.PicoContainer;
012    import org.picocontainer.PicoVerificationException;
013    import org.picocontainer.PicoVisitor;
014    
015    /**
016     *  
017     * @author Michael Rimov
018     */
019    public class CommonsLoggingTracingContainerDecorator implements MutablePicoContainer {
020            
021            /**
022             * Wrapped container.
023             */
024            private final MutablePicoContainer delegate;
025            
026            /**
027             * Logger instance used for writing events.
028             */
029            private transient Log log;
030            
031            /**
032             * Serialized log category.
033             */
034            private final String logCategory;
035            
036            /**
037             * Default typical wrapper that wraps another MutablePicoContainer.
038             * @param delegate Container to be decorated.
039             * @throws NullPointerException if delegate is null.
040             */
041            public CommonsLoggingTracingContainerDecorator(final MutablePicoContainer delegate) {
042                    this(delegate, PicoContainer.class.getName());
043            }
044            
045            
046            /**
047             * Alternate constructor that allows specification of the Logger to
048             * use.
049             * @param delegate Container to be decorated.
050             * @param log specific Log4j Logger to use.
051             * @throws NullPointerException if delegate or log is null.
052             */
053            public CommonsLoggingTracingContainerDecorator(final MutablePicoContainer delegate, final String loggingCategory) {
054                    if (delegate == null) {
055                            throw new NullPointerException("delegate");
056                    }
057                    
058                    if (loggingCategory == null) {
059                            throw new NullPointerException("loggingCategory");
060                    }
061                    
062                    log = LogFactory.getLog(loggingCategory);
063                    
064                    this.delegate = delegate;
065                    logCategory = loggingCategory;
066            }
067            
068            
069            /**
070             * Standard message handling for cases when a null object is returned
071             * for a given key.
072             * @param componentKey
073             * @param target
074             */
075            protected void onKeyDoesntExistInContainer(final Object componentKey, final Log target) {
076                    log.info("Could not find component "
077                                    + ((componentKey != null) ? componentKey.toString() : " null ")
078                                    + " in container or parent container.");
079            }
080    
081            /**
082             * {@inheritDoc}
083             * @param visitor
084             * @see org.picocontainer.PicoContainer#accept(org.picocontainer.PicoVisitor)
085             */
086            public void accept(final PicoVisitor visitor) {
087                    if (log.isDebugEnabled()) {
088                            log.debug("Visiting Container " + delegate
089                                            + " with visitor " + visitor);
090                    }
091                    delegate.accept(visitor);
092            }
093    
094            /**
095             * {@inheritDoc}
096             * @param child
097             * @return
098             * @see org.picocontainer.MutablePicoContainer#addChildContainer(org.picocontainer.PicoContainer)
099             */
100            public boolean addChildContainer(final PicoContainer child) {
101                    if (log.isDebugEnabled()) {
102                            log.debug("Adding child container: " + child + " to container " + delegate);
103                    }
104                    return delegate.addChildContainer(child);
105            }
106    
107            /**
108             * {@inheritDoc}
109             * @see org.picocontainer.Disposable#dispose()
110             */
111            public void dispose() {
112                    if (log.isDebugEnabled()) {
113                            log.debug("Disposing container " + delegate);
114                    }
115                    delegate.dispose();
116            }
117    
118            /**
119             * {@inheritDoc}
120             * @param componentKey
121             * @return
122             * @see org.picocontainer.PicoContainer#getComponentAdapter(java.lang.Object)
123             */
124            public ComponentAdapter getComponentAdapter(final Object componentKey) {
125                    if (log.isDebugEnabled()) {
126                            log.debug("Locating component adapter with key " + componentKey);
127                    }
128                    
129                    ComponentAdapter adapter =  delegate.getComponentAdapter(componentKey);
130                    if (adapter == null) {
131                            onKeyDoesntExistInContainer(componentKey, log);
132                    }
133                    return adapter;
134            }
135    
136            /**
137             * {@inheritDoc}
138             * @param componentType
139             * @return ComponentAdapter or null.
140             * @see org.picocontainer.PicoContainer#getComponentAdapterOfType(java.lang.Class)
141             */
142            public ComponentAdapter getComponentAdapterOfType(final Class componentType) {
143                    if (log.isDebugEnabled()) {
144                            log.debug("Locating component adapter with type " + componentType);
145                    }
146    
147                    ComponentAdapter ca =  delegate.getComponentAdapterOfType(componentType);
148    
149                    if (ca == null) {
150                            onKeyDoesntExistInContainer(ca, log);
151                    }
152                    return ca;
153            }
154    
155            /**
156             * {@inheritDoc}
157             * @return Collection or null.
158             * @see org.picocontainer.PicoContainer#getComponentAdapters()
159             */
160            public Collection getComponentAdapters() {
161                    if (log.isDebugEnabled()) {
162                            log.debug("Grabbing all component adapters for container: " + delegate);
163                    }
164                    return delegate.getComponentAdapters();
165            }
166    
167            /**
168             * {@inheritDoc}
169             * @param componentType
170             * @return List of ComponentAdapters
171             * @see org.picocontainer.PicoContainer#getComponentAdaptersOfType(java.lang.Class)
172             */
173            public List getComponentAdaptersOfType(final Class componentType) {
174                    if (log.isDebugEnabled()) {
175                            log.debug("Grabbing all component adapters for container: " 
176                                            + delegate + " of type: " + componentType.getName());
177                    }
178                    return delegate.getComponentAdaptersOfType(componentType);
179            }
180    
181            /**
182             * {@inheritDoc}
183             * @param componentKey
184             * @return
185             * @see org.picocontainer.PicoContainer#getComponentInstance(java.lang.Object)
186             */
187            public Object getComponentInstance(final Object componentKey) {
188                    
189                    if (log.isDebugEnabled()) {
190                            log.debug("Attempting to load component instance with key: " 
191                                            + componentKey
192                                            + " for container " 
193                                            + delegate);
194                            
195                    }
196                    
197                    Object result =  delegate.getComponentInstance(componentKey);
198                    if (result == null) {
199                            onKeyDoesntExistInContainer(componentKey, log);
200                    }
201                    
202                    return result;
203            }
204    
205            /**
206             * {@inheritDoc}
207             * @param componentType
208             * @return
209             * @see org.picocontainer.PicoContainer#getComponentInstanceOfType(java.lang.Class)
210             */
211            public Object getComponentInstanceOfType(final Class componentType) {
212                    if (log.isDebugEnabled()) {
213                            log.debug("Attempting to load component instance with type: " 
214                                            + componentType
215                                            + " for container " 
216                                            + delegate);
217                            
218                    }
219                    
220                    Object result = delegate.getComponentInstanceOfType(componentType);
221                    if (result == null) {
222                            if (log.isInfoEnabled()) {
223                                    log.info("No component of type " + componentType.getName()
224                                                    + " was found in container: " + delegate);
225                            }
226                    }
227                    
228                    return result;
229            }
230    
231            /**
232             * {@inheritDoc}
233             * @return
234             * @see org.picocontainer.PicoContainer#getComponentInstances()
235             */
236            public List getComponentInstances() {
237                    if (log.isDebugEnabled()) {
238                            log.debug("Retrieving all component instances for container "
239                                            + delegate);
240                    }
241                    return delegate.getComponentInstances();
242            }
243    
244            /**
245             * {@inheritDoc}
246             * @param componentType
247             * @return
248             * @see org.picocontainer.PicoContainer#getComponentInstancesOfType(java.lang.Class)
249             */
250            public List getComponentInstancesOfType(final Class componentType) {
251                    if (log.isDebugEnabled()) {
252                            log.debug("Loading all component instances of type " + componentType
253                                            + " for container " + delegate);
254                    }
255                    List result = delegate.getComponentInstancesOfType(componentType);
256                    if (result == null || result.size() == 0) {
257                            if (log.isInfoEnabled()) {
258                            log.info("Could not find any components  "
259                                            + " in container or parent container.");        
260                            }
261                    }
262                    
263                    return result;
264            }
265    
266            /**
267             * {@inheritDoc}
268             * @return
269             * @see org.picocontainer.PicoContainer#getParent()
270             */
271            public PicoContainer getParent() {
272                    if (log.isDebugEnabled()) {
273                            log.debug("Retrieving the parent for container " + delegate);
274                    }
275                    
276                    return delegate.getParent();
277            }
278    
279            /**
280             * {@inheritDoc}
281             * @return
282             * @see org.picocontainer.MutablePicoContainer#makeChildContainer()
283             */
284            public MutablePicoContainer makeChildContainer() {
285                    if (log.isDebugEnabled()) {
286                            log.debug("Making child container for container " + delegate);
287                    }
288                    
289                    //Wrap the new delegate
290                    return new Log4jTracingContainerDecorator( delegate.makeChildContainer());
291            }
292    
293            /**
294             * {@inheritDoc}
295             * @param componentAdapter
296             * @return
297             * @see org.picocontainer.MutablePicoContainer#registerComponent(org.picocontainer.ComponentAdapter)
298             */
299            public ComponentAdapter registerComponent(final ComponentAdapter componentAdapter) {
300                    if (log.isDebugEnabled()) {
301                            log.debug("Registering component adapter " + componentAdapter);
302                    }
303                    
304                    return delegate.registerComponent(componentAdapter);
305            }
306    
307            /**
308             * {@inheritDoc}
309             * @param componentImplementation
310             * @return
311             * @see org.picocontainer.MutablePicoContainer#registerComponentImplementation(java.lang.Class)
312             */
313            public ComponentAdapter registerComponentImplementation(final Class componentImplementation) {
314                    if (log.isDebugEnabled()) {
315                            log.debug("Registering component implementation " + componentImplementation.getName());
316                    }
317    
318                    return delegate.registerComponentImplementation(componentImplementation);
319            }
320    
321            /**
322             * {@inheritDoc}
323             * @param componentKey
324             * @param componentImplementation
325             * @param parameters
326             * @return
327             * @see org.picocontainer.MutablePicoContainer#registerComponentImplementation(java.lang.Object, java.lang.Class, org.picocontainer.Parameter[])
328             */
329            public ComponentAdapter registerComponentImplementation(final Object componentKey, final Class componentImplementation, 
330                            final Parameter[] parameters) {
331                    if (log.isDebugEnabled()) {
332                            log.debug("Registering component implementation with key " 
333                                            + componentKey 
334                                            + " and implementation " 
335                                            + componentImplementation.getName() 
336                                            + " using parameters "
337                                            + parameters);
338                    }
339                    
340                    return delegate.registerComponentImplementation(componentKey, componentImplementation, parameters);
341            }
342    
343            /**
344             * {@inheritDoc}
345             * @param componentKey
346             * @param componentImplementation
347             * @return
348             * @see org.picocontainer.MutablePicoContainer#registerComponentImplementation(java.lang.Object, java.lang.Class)
349             */
350            public ComponentAdapter registerComponentImplementation(final Object componentKey, final Class componentImplementation) {
351                    if (log.isDebugEnabled()) {
352                            log.debug("Registering component implementation with key " 
353                                            + componentKey 
354                                            + " and implementation " 
355                                            + componentImplementation.getName());
356                    }
357                    
358                    return delegate.registerComponentImplementation(componentKey, componentImplementation);
359            }
360    
361            /**
362             * {@inheritDoc}
363             * @param componentKey
364             * @param componentInstance
365             * @return
366             * @see org.picocontainer.MutablePicoContainer#registerComponentInstance(java.lang.Object, java.lang.Object)
367             */
368            public ComponentAdapter registerComponentInstance(final Object componentKey, final Object componentInstance) {
369                    if (log.isDebugEnabled()) {
370                            log.debug("Registering component instance with key " 
371                                            + componentKey 
372                                            + " and instance " 
373                                            + componentInstance + "(class: " 
374                                            + ((componentInstance != null) ? componentInstance.getClass().getName() : " null "));
375                    }
376    
377                    return delegate.registerComponentInstance(componentKey, componentInstance);
378            }
379    
380            /**
381             * {@inheritDoc}
382             * @param componentInstance
383             * @return
384             * @see org.picocontainer.MutablePicoContainer#registerComponentInstance(java.lang.Object)
385             */
386            public ComponentAdapter registerComponentInstance(final Object componentInstance) {
387                    if (log.isDebugEnabled()) {
388                            log.debug("Registering component instance " 
389                                            + componentInstance + "(class: " 
390                                            + ((componentInstance != null) ? componentInstance.getClass().getName() : " null "));
391                    }
392                    
393                    return delegate.registerComponentInstance(componentInstance);
394            }
395    
396            /**
397             * {@inheritDoc}
398             * @param child
399             * @return
400             * @see org.picocontainer.MutablePicoContainer#removeChildContainer(org.picocontainer.PicoContainer)
401             */
402            public boolean removeChildContainer(final PicoContainer child) {
403                    if (log.isDebugEnabled()) {
404                            log.debug("Removing child container: " + child
405                                            + " from parent: " + delegate);
406                    }
407                    return delegate.removeChildContainer(child);
408            }
409    
410            /**
411             * {@inheritDoc}
412             * @see org.picocontainer.Startable#start()
413             */
414            public void start() {
415                    if (log.isInfoEnabled()) {
416                            log.info("Starting Container " + delegate);
417                    }
418                    
419                    delegate.start();
420            }
421    
422            /**
423             * {@inheritDoc}
424             * @see org.picocontainer.Startable#stop()
425             */
426            public void stop() {
427                    if (log.isInfoEnabled()) {
428                            log.info("Stopping Container " + delegate);
429                    }
430                    delegate.stop();
431            }
432    
433            /**
434             * {@inheritDoc}
435             * @param componentKey
436             * @return
437             * @see org.picocontainer.MutablePicoContainer#unregisterComponent(java.lang.Object)
438             */
439            public ComponentAdapter unregisterComponent(final Object componentKey) {
440                    if (log.isDebugEnabled()) {
441                            log.debug("Unregistering component " + componentKey + " from container " + delegate);
442                    }
443                    
444                    return delegate.unregisterComponent(componentKey);
445            }
446    
447            /**
448             * {@inheritDoc}
449             * @param componentInstance
450             * @return
451             * @see org.picocontainer.MutablePicoContainer#unregisterComponentByInstance(java.lang.Object)
452             */
453            public ComponentAdapter unregisterComponentByInstance(final Object componentInstance) {
454                    if (log.isDebugEnabled()) {
455                            log.debug("Unregistering component by instance (" + componentInstance + ") from container " + delegate);
456                    }
457                    
458                    return delegate.unregisterComponentByInstance(componentInstance);
459            }
460    
461            /**
462             * {@inheritDoc}
463             * @throws PicoVerificationException
464             * @deprecated
465             * @see org.picocontainer.PicoContainer#verify()
466             */
467            public void verify() throws PicoVerificationException {
468                    log.info("Verifying container");
469                    log.warn("Using deprecated function PicoContainer.verify().  Please use VerifyingVisitor instead.");
470                    delegate.verify();
471            }
472            
473            
474            /**
475             * Retrieves the log instance used by this decorator.
476             * @return Logger instance.
477             */
478            public Log getLoggerUsed() {
479                    return this.log;
480            }
481            
482            private void readObject(final java.io.ObjectInputStream s) 
483                    throws java.io.IOException, java.lang.ClassNotFoundException {
484                    s.defaultReadObject();
485                    log = LogFactory.getLog(this.logCategory);
486            }
487    }