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 }